Convert struct target_ops to C++

I.e., use C++ virtual methods and inheritance instead of tables of
function pointers.

Unfortunately, there's no way to do a smooth transition.  ALL native
targets in the tree must be converted at the same time.  I've tested
all I could with cross compilers and with help from GCC compile farm,
but naturally I haven't been able to test many of the ports.  Still, I
made a best effort to port everything over, and while I expect some
build problems due to typos and such, which should be trivial to fix,
I don't expect any design problems.

* Implementation notes:

- The flattened current_target is gone.  References to current_target
  or current_target.beneath are replaced with references to
  target_stack (the top of the stack) directly.

- To keep "set debug target" working, this adds a new debug_stratum
  layer that sits on top of the stack, prints the debug, and delegates
  to the target beneath.

  In addition, this makes the shortname and longname properties of
  target_ops be virtual methods instead of data fields, and makes the
  debug target defer those to the target beneath.  This is so that
  debug code sprinkled around that does "if (debugtarget) ..."  can
  transparently print the name of the target beneath.

  A patch later in the series actually splits out the
  shortname/longname methods to a separate structure, but I preferred
  to keep that chance separate as it is associated with changing a bit
  the design of how targets are registered and open.

- Since you can't check whether a C++ virtual method is overridden,
  the old method of checking whether a target_ops implements a method
  by comparing the function pointer must be replaced with something
  else.

  Some cases are fixed by adding a parallel "can_do_foo" target_ops
  methods.  E.g.,:

    +  for (t = target_stack; t != NULL; t = t->beneath)
	 {
    -      if (t->to_create_inferior != NULL)
    +      if (t->can_create_inferior ())
	    break;
	 }

  Others are fixed by changing void return type to bool or int return
  type, and have the default implementation return false or -1, to
  indicate lack of support.

- make-target-delegates was adjusted to generate C++ classes and
  methods.

  It needed tweaks to grok "virtual" in front of the target method
  name, and for the fact that methods are no longer function pointers.
  (In particular, the current code parsing the return type was simple
  because it could simply parse up until the '(' in '(*to_foo)'.

  It now generates a couple C++ classes that inherit target_ops:
  dummy_target and debug_target.

  Since we need to generate the class declarations as well, i.e., we
  need to emit methods twice, we now generate the code in two passes.

- The core_target global is renamed to avoid conflict with the
  "core_target" class.

- ctf/tfile targets

  init_tracefile_ops is replaced by a base class that is inherited by
  both ctf and tfile.

- bsd-uthread

  The bsd_uthread_ops_hack hack is gone.  It's not needed because
  nothing was extending a target created by bsd_uthread_target.

- remote/extended-remote targets

  This is a first pass, just enough to C++ify target_ops.

  A later pass will convert more free functions to methods, and make
  remote_state be truly per remote instance, allowing multiple
  simultaneous instances of remote targets.

- inf-child/"native" is converted to an actual base class
  (inf_child_target), that is inherited by all native targets.

- GNU/Linux

  The old weird double-target linux_ops mechanism in linux-nat.c, is
  gone, replaced by adding a few virtual methods to linux-nat.h's
  target_ops, called low_XXX, that the concrete linux-nat
  implementations override.  Sort of like gdbserver's
  linux_target_ops, but simpler, for requiring only one
  target_ops-like hierarchy, which spares implementing the same method
  twice when we need to forward the method to a low implementation.
  The low target simply reimplements the target_ops method directly in
  that case.

  There are a few remaining linux-nat.c hooks that would be better
  converted to low_ methods like above too.  E.g.:

   linux_nat_set_new_thread (t, x86_linux_new_thread);
   linux_nat_set_new_fork (t, x86_linux_new_fork);
   linux_nat_set_forget_process

  That'll be done in a follow up patch.

- We can no longer use functions like x86_use_watchpoints to install
  custom methods on an arbitrary base target.

  The patch replaces instances of such a pattern with template mixins.
  For example memory_breakpoint_target defined in target.h, or
  x86_nat_target in x86-nat.h.

- linux_trad_target, MIPS and Alpha GNU/Linux

  The code in the new linux-nat-trad.h/c files which was split off of
  inf-ptrace.h/c recently, is converted to a C++ base class, and used
  by the MIPS and Alpha GNU/Linux ports.

- BSD targets

  The

    $architecture x NetBSD/OpenBSD/FreeBSD

  support matrix complicates things a bit.  There's common BSD target
  code, and there's common architecture-specific code shared between
  the different BSDs.  Currently, all that is stiched together to form
  a final target, via the i386bsd_target, x86bsd_target,
  fbsd_nat_add_target functions etc.

  This introduces new fbsd_nat_target, obsd_nat_target and
  nbsd_nat_target classes that serve as base/prototype target for the
  corresponding BSD variant.

  And introduces generic i386/AMD64 BSD targets, to be used as
  template mixin to build a final target.  Similarly, a generic SPARC
  target is added, used by both BSD and Linux ports.

- bsd_kvm_add_target, BSD libkvm target

  I considered making bsd_kvm_supply_pcb a virtual method, and then
  have each port inherit bsd_kvm_target and override that method, but
  that was resulting in lots of unjustified churn, so I left the
  function pointer mechanism alone.

gdb/ChangeLog:
2018-05-02  Pedro Alves  <palves@redhat.com>
	    John Baldwin  <jhb@freebsd.org>

	* target.h (enum strata) <debug_stratum>: New.
	(struct target_ops) <all delegation methods>: Replace by C++
	virtual methods, and drop "to_" prefix.  All references updated
	throughout.
	<to_shortname, to_longname, to_doc, to_data,
	to_have_steppable_watchpoint, to_have_continuable_watchpoint,
	to_has_thread_control, to_attach_no_wait>: Delete, replaced by
	virtual methods.  All references updated throughout.
	<can_attach, supports_terminal_ours, can_create_inferior,
	get_thread_control_capabilities, attach_no_wait>: New
	virtual methods.
	<insert_breakpoint, remove_breakpoint>: Now
	TARGET_DEFAULT_NORETURN methods.
	<info_proc>: Now returns bool.
	<to_magic>: Delete.
	(OPS_MAGIC): Delete.
	(current_target): Delete.  All references replaced by references
	to ...
	(target_stack): ... this.  New.
	(target_shortname, target_longname): Adjust.
	(target_can_run): Now a function declaration.
	(default_child_has_all_memory, default_child_has_memory)
	(default_child_has_stack, default_child_has_registers)
	(default_child_has_execution): Remove target_ops parameter.
	(complete_target_initialization): Delete.
	(memory_breakpoint_target): New template class.
	(test_target_ops): Refactor as a C++ class with virtual methods.
	* make-target-delegates (NAME_PART): Tighten.
	(POINTER_PART, CP_SYMBOL): New.
	(SIMPLE_RETURN_PART): Reimplement.
	(VEC_RETURN_PART): Expect less.
	(RETURN_PART, VIRTUAL_PART): New.
	(METHOD): Adjust to C++ virtual methods.
	(scan_target_h): Remove reference to C99.
	(dname): Output "target_ops::" prefix.
	(write_function_header): Adjust to output a C++ class method.
	(write_declaration): New.
	(write_delegator): Adjust to output a C++ class method.
	(tdname): Output "dummy_target::" prefix.
	(write_tdefault, write_debugmethod): Adjust to output a C++ class
	method.
	(tdefault_names, debug_names): Delete.
	(return_types, tdefaults, styles, argtypes_array): New.
	(top level): All methods are delegators.
	(print_class): New.
	(top level): Print dummy_target and debug_target classes.
	* target-delegates.c: Regenerate.
	* target-debug.h (target_debug_print_enum_info_proc_what)
	(target_debug_print_thread_control_capabilities)
	(target_debug_print_thread_info_p): New.
	* target.c (dummy_target): Delete.
	(the_dummy_target, the_debug_target): New.
	(target_stack): Now extern.
	(set_targetdebug): Push/unpush debug target.
	(default_child_has_all_memory, default_child_has_memory)
	(default_child_has_stack, default_child_has_registers)
	(default_child_has_execution): Remove target_ops parameter.
	(complete_target_initialization): Delete.
	(add_target_with_completer): No longer call
	complete_target_initialization.
	(target_supports_terminal_ours): Use regular delegation.
	(update_current_target): Delete.
	(push_target): No longer check magic number.  Don't call
	update_current_target.
	(unpush_target): Don't call update_current_target.
	(target_is_pushed): No longer check magic number.
	(target_require_runnable): Skip for all stratums over
	process_stratum.
	(target_ops::info_proc): New.
	(target_info_proc): Use find_target_at and
	find_default_run_target.
	(target_supports_disable_randomization): Use regular delegation.
	(target_get_osdata): Use find_target_at.
	(target_ops::open, target_ops::close, target_ops::can_attach)
	(target_ops::attach, target_ops::can_create_inferior)
	(target_ops::create_inferior, target_ops::can_run)
	(target_can_run): New.
	(default_fileio_target): Use regular delegation.
	(target_ops::fileio_open, target_ops::fileio_pwrite)
	(target_ops::fileio_pread, target_ops::fileio_fstat)
	(target_ops::fileio_close, target_ops::fileio_unlink)
	(target_ops::fileio_readlink): New.
	(target_fileio_open_1, target_fileio_unlink)
	(target_fileio_readlink): Always call the target method.  Handle
	FILEIO_ENOSYS.
	(return_zero, return_zero_has_execution): Delete.
	(init_dummy_target): Delete.
	(dummy_target::dummy_target, dummy_target::shortname)
	(dummy_target::longname, dummy_target::doc)
	(debug_target::debug_target, debug_target::shortname)
	(debug_target::longname, debug_target::doc): New.
	(target_supports_delete_record): Use regular delegation.
	(setup_target_debug): Delete.
	(maintenance_print_target_stack): Skip debug_stratum.
	(initialize_targets): Instantiate the_dummy_target and
	the_debug_target.
	* auxv.c (target_auxv_parse): Remove 'ops' parameter.  Adjust to
	use target_stack.
	(target_auxv_search, fprint_target_auxv): Adjust.
	(info_auxv_command): Adjust to use target_stack.
	* auxv.h (target_auxv_parse): Remove 'ops' parameter.
	* exceptions.c (print_flush): Handle a NULL target_stack.
	* regcache.c (target_ops_no_register): Refactor as class with
	virtual methods.

	* exec.c (exec_target): New class.
	(exec_ops): Now an exec_target.
	(exec_open, exec_close_1, exec_get_section_table)
	(exec_xfer_partial, exec_files_info, exec_has_memory)
	(exec_make_note_section): Refactor as exec_target methods.
	(exec_file_clear, ignore, exec_remove_breakpoint, init_exec_ops):
	Delete.
	(exec_target::find_memory_regions): New.
	(_initialize_exec): Don't call init_exec_ops.
	* gdbcore.h (exec_file_clear): Delete.

	* corefile.c (core_target): Delete.
	(core_file_command): Adjust.
	* corelow.c (core_target): New class.
	(the_core_target): New.
	(core_close): Remove target_ops parameter.
	(core_close_cleanup): Adjust.
	(core_target::close): New.
	(core_open, core_detach, get_core_registers, core_files_info)
	(core_xfer_partial, core_thread_alive, core_read_description)
	(core_pid_to_str, core_thread_name, core_has_memory)
	(core_has_stack, core_has_registers, core_info_proc): Rework as
	core_target methods.
	(ignore, core_remove_breakpoint, init_core_ops): Delete.
	(_initialize_corelow): Initialize the_core_target.
	* gdbcore.h (core_target): Delete.
	(the_core_target): New.

	* ctf.c: (ctf_target): New class.
	(ctf_ops): Now a ctf_target.
	(ctf_open, ctf_close, ctf_files_info, ctf_fetch_registers)
	(ctf_xfer_partial, ctf_get_trace_state_variable_value)
	(ctf_trace_find, ctf_traceframe_info): Refactor as ctf_target
	methods.
	(init_ctf_ops): Delete.
	(_initialize_ctf): Don't call it.
	* tracefile-tfile.c (tfile_target): New class.
	(tfile_ops): Now a tfile_target.
	(tfile_open, tfile_close, tfile_files_info)
	(tfile_get_tracepoint_status, tfile_trace_find)
	(tfile_fetch_registers, tfile_xfer_partial)
	(tfile_get_trace_state_variable_value, tfile_traceframe_info):
	Refactor as tfile_target methods.
	(tfile_xfer_partial_features): Remove target_ops parameter.
	(init_tfile_ops): Delete.
	(_initialize_tracefile_tfile): Don't call it.
	* tracefile.c (tracefile_has_all_memory, tracefile_has_memory)
	(tracefile_has_stack, tracefile_has_registers)
	(tracefile_thread_alive, tracefile_get_trace_status): Refactor as
	tracefile_target methods.
	(init_tracefile_ops): Delete.
	(tracefile_target::tracefile_target): New.
	* tracefile.h: Include "target.h".
	(tracefile_target): New class.
	(init_tracefile_ops): Delete.

	* spu-multiarch.c (spu_multiarch_target): New class.
	(spu_ops): Now a spu_multiarch_target.
	(spu_thread_architecture, spu_region_ok_for_hw_watchpoint)
	(spu_fetch_registers, spu_store_registers, spu_xfer_partial)
	(spu_search_memory, spu_mourn_inferior): Refactor as
	spu_multiarch_target methods.
	(init_spu_ops): Delete.
	(_initialize_spu_multiarch): Remove references to init_spu_ops,
	complete_target_initialization.

	* ravenscar-thread.c (ravenscar_thread_target): New class.
	(ravenscar_ops): Now a ravenscar_thread_target.
	(ravenscar_resume, ravenscar_wait, ravenscar_update_thread_list)
	(ravenscar_thread_alive, ravenscar_pid_to_str)
	(ravenscar_fetch_registers, ravenscar_store_registers)
	(ravenscar_prepare_to_store, ravenscar_stopped_by_sw_breakpoint)
	(ravenscar_stopped_by_hw_breakpoint)
	(ravenscar_stopped_by_watchpoint, ravenscar_stopped_data_address)
	(ravenscar_mourn_inferior, ravenscar_core_of_thread)
	(ravenscar_get_ada_task_ptid): Refactor as ravenscar_thread_target
	methods.
	(init_ravenscar_thread_ops): Delete.
	(_initialize_ravenscar): Remove references to
	init_ravenscar_thread_ops and complete_target_initialization.

	* bsd-uthread.c (bsd_uthread_ops_hack): Delete.
	(bsd_uthread_target): New class.
	(bsd_uthread_ops): Now a bsd_uthread_target.
	(bsd_uthread_activate): Adjust to refer to bsd_uthread_ops.
	(bsd_uthread_close, bsd_uthread_mourn_inferior)
	(bsd_uthread_fetch_registers, bsd_uthread_store_registers)
	(bsd_uthread_wait, bsd_uthread_resume, bsd_uthread_thread_alive)
	(bsd_uthread_update_thread_list, bsd_uthread_extra_thread_info)
	(bsd_uthread_pid_to_str): Refactor as bsd_uthread_target methods.
	(bsd_uthread_target): Delete function.
	(_initialize_bsd_uthread): Remove reference to
	complete_target_initialization.

	* bfd-target.c (target_bfd_data): Delete.  Fields folded into ...
	(target_bfd): ... this new class.
	(target_bfd_xfer_partial, target_bfd_get_section_table)
	(target_bfd_close): Refactor as target_bfd methods.
	(target_bfd::~target_bfd): New.
	(target_bfd_reopen): Adjust.
	(target_bfd::close): New.

	* record-btrace.c (record_btrace_target): New class.
	(record_btrace_ops): Now a record_btrace_target.
	(record_btrace_open, record_btrace_stop_recording)
	(record_btrace_disconnect, record_btrace_close)
	(record_btrace_async, record_btrace_info)
	(record_btrace_insn_history, record_btrace_insn_history_range)
	(record_btrace_insn_history_from, record_btrace_call_history)
	(record_btrace_call_history_range)
	(record_btrace_call_history_from, record_btrace_record_method)
	(record_btrace_is_replaying, record_btrace_will_replay)
	(record_btrace_xfer_partial, record_btrace_insert_breakpoint)
	(record_btrace_remove_breakpoint, record_btrace_fetch_registers)
	(record_btrace_store_registers, record_btrace_prepare_to_store)
	(record_btrace_to_get_unwinder)
	(record_btrace_to_get_tailcall_unwinder, record_btrace_resume)
	(record_btrace_commit_resume, record_btrace_wait)
	(record_btrace_stop, record_btrace_can_execute_reverse)
	(record_btrace_stopped_by_sw_breakpoint)
	(record_btrace_supports_stopped_by_sw_breakpoint)
	(record_btrace_stopped_by_hw_breakpoint)
	(record_btrace_supports_stopped_by_hw_breakpoint)
	(record_btrace_update_thread_list, record_btrace_thread_alive)
	(record_btrace_goto_begin, record_btrace_goto_end)
	(record_btrace_goto, record_btrace_stop_replaying_all)
	(record_btrace_execution_direction)
	(record_btrace_prepare_to_generate_core)
	(record_btrace_done_generating_core): Refactor as
	record_btrace_target methods.
	(init_record_btrace_ops): Delete.
	(_initialize_record_btrace): Remove reference to
	init_record_btrace_ops.
	* record-full.c (RECORD_FULL_IS_REPLAY): Adjust to always refer to
	the execution_direction global.
	(record_full_base_target, record_full_target)
	(record_full_core_target): New classes.
	(record_full_ops): Now a record_full_target.
	(record_full_core_ops): Now a record_full_core_target.
	(record_full_target::detach, record_full_target::disconnect)
	(record_full_core_target::disconnect)
	(record_full_target::mourn_inferior, record_full_target::kill):
	New.
	(record_full_open, record_full_close, record_full_async): Refactor
	as methods of the record_full_base_target class.
	(record_full_resume, record_full_commit_resume): Refactor
	as methods of the record_full_target class.
	(record_full_wait, record_full_stopped_by_watchpoint)
	(record_full_stopped_data_address)
	(record_full_stopped_by_sw_breakpoint)
	(record_full_supports_stopped_by_sw_breakpoint)
	(record_full_stopped_by_hw_breakpoint)
	(record_full_supports_stopped_by_hw_breakpoint): Refactor as
	methods of the record_full_base_target class.
	(record_full_store_registers, record_full_xfer_partial)
	(record_full_insert_breakpoint, record_full_remove_breakpoint):
	Refactor as methods of the record_full_target class.
	(record_full_can_execute_reverse, record_full_get_bookmark)
	(record_full_goto_bookmark, record_full_execution_direction)
	(record_full_record_method, record_full_info, record_full_delete)
	(record_full_is_replaying, record_full_will_replay)
	(record_full_goto_begin, record_full_goto_end, record_full_goto)
	(record_full_stop_replaying): Refactor as methods of the
	record_full_base_target class.
	(record_full_core_resume, record_full_core_kill)
	(record_full_core_fetch_registers)
	(record_full_core_prepare_to_store)
	(record_full_core_store_registers, record_full_core_xfer_partial)
	(record_full_core_insert_breakpoint)
	(record_full_core_remove_breakpoint)
	(record_full_core_has_execution): Refactor
	as methods of the record_full_core_target class.
	(record_full_base_target::supports_delete_record): New.
	(init_record_full_ops): Delete.
	(init_record_full_core_ops): Delete.
	(record_full_save): Refactor as method of the
	record_full_base_target class.
	(_initialize_record_full): Remove references to
	init_record_full_ops and init_record_full_core_ops.

	* remote.c (remote_target, extended_remote_target): New classes.
	(remote_ops): Now a remote_target.
	(extended_remote_ops): Now an extended_remote_target.
	(remote_insert_fork_catchpoint, remote_remove_fork_catchpoint)
	(remote_insert_vfork_catchpoint, remote_remove_vfork_catchpoint)
	(remote_insert_exec_catchpoint, remote_remove_exec_catchpoint)
	(remote_pass_signals, remote_set_syscall_catchpoint)
	(remote_program_signals, )
	(remote_thread_always_alive): Remove target_ops parameter.
	(remote_thread_alive, remote_thread_name)
	(remote_update_thread_list, remote_threads_extra_info)
	(remote_static_tracepoint_marker_at)
	(remote_static_tracepoint_markers_by_strid)
	(remote_get_ada_task_ptid, remote_close, remote_start_remote)
	(remote_open): Refactor as methods of remote_target.
	(extended_remote_open, extended_remote_detach)
	(extended_remote_attach, extended_remote_post_attach):
	(extended_remote_supports_disable_randomization)
	(extended_remote_create_inferior): : Refactor as method of
	extended_remote_target.
	(remote_set_permissions, remote_open_1, remote_detach)
	(remote_follow_fork, remote_follow_exec, remote_disconnect)
	(remote_resume, remote_commit_resume, remote_stop)
	(remote_interrupt, remote_pass_ctrlc, remote_terminal_inferior)
	(remote_terminal_ours, remote_wait, remote_fetch_registers)
	(remote_prepare_to_store, remote_store_registers)
	(remote_flash_erase, remote_flash_done, remote_files_info)
	(remote_kill, remote_mourn, remote_insert_breakpoint)
	(remote_remove_breakpoint, remote_insert_watchpoint)
	(remote_watchpoint_addr_within_range)
	(remote_remove_watchpoint, remote_region_ok_for_hw_watchpoint)
	(remote_check_watch_resources, remote_stopped_by_sw_breakpoint)
	(remote_supports_stopped_by_sw_breakpoint)
	(remote_stopped_by_hw_breakpoint)
	(remote_supports_stopped_by_hw_breakpoint)
	(remote_stopped_by_watchpoint, remote_stopped_data_address)
	(remote_insert_hw_breakpoint, remote_remove_hw_breakpoint)
	(remote_verify_memory): Refactor as methods of remote_target.
	(remote_write_qxfer, remote_read_qxfer): Remove target_ops
	parameter.
	(remote_xfer_partial, remote_get_memory_xfer_limit)
	(remote_search_memory, remote_rcmd, remote_memory_map)
	(remote_pid_to_str, remote_get_thread_local_address)
	(remote_get_tib_address, remote_read_description): Refactor as
	methods of remote_target.
	(remote_target::fileio_open, remote_target::fileio_pwrite)
	(remote_target::fileio_pread, remote_target::fileio_close): New.
	(remote_hostio_readlink, remote_hostio_fstat)
	(remote_filesystem_is_local, remote_can_execute_reverse)
	(remote_supports_non_stop, remote_supports_disable_randomization)
	(remote_supports_multi_process, remote_supports_cond_breakpoints)
	(remote_supports_enable_disable_tracepoint)
	(remote_supports_string_tracing)
	(remote_can_run_breakpoint_commands, remote_trace_init)
	(remote_download_tracepoint, remote_can_download_tracepoint)
	(remote_download_trace_state_variable, remote_enable_tracepoint)
	(remote_disable_tracepoint, remote_trace_set_readonly_regions)
	(remote_trace_start, remote_get_trace_status)
	(remote_get_tracepoint_status, remote_trace_stop)
	(remote_trace_find, remote_get_trace_state_variable_value)
	(remote_save_trace_data, remote_get_raw_trace_data)
	(remote_set_disconnected_tracing, remote_core_of_thread)
	(remote_set_circular_trace_buffer, remote_traceframe_info)
	(remote_get_min_fast_tracepoint_insn_len)
	(remote_set_trace_buffer_size, remote_set_trace_notes)
	(remote_use_agent, remote_can_use_agent, remote_enable_btrace)
	(remote_disable_btrace, remote_teardown_btrace)
	(remote_read_btrace, remote_btrace_conf)
	(remote_augmented_libraries_svr4_read, remote_load)
	(remote_pid_to_exec_file, remote_can_do_single_step)
	(remote_execution_direction, remote_thread_handle_to_thread_info):
	Refactor as methods of remote_target.
	(init_remote_ops, init_extended_remote_ops): Delete.
	(remote_can_async_p, remote_is_async_p, remote_async)
	(remote_thread_events, remote_upload_tracepoints)
	(remote_upload_trace_state_variables): Refactor as methods of
	remote_target.
	(_initialize_remote): Remove references to init_remote_ops and
	init_extended_remote_ops.

	* remote-sim.c (gdbsim_target): New class.
	(gdbsim_fetch_register, gdbsim_store_register, gdbsim_kill)
	(gdbsim_load, gdbsim_create_inferior, gdbsim_open, gdbsim_close)
	(gdbsim_detach, gdbsim_resume, gdbsim_interrupt)
	(gdbsim_wait, gdbsim_prepare_to_store, gdbsim_xfer_partial)
	(gdbsim_files_info, gdbsim_mourn_inferior, gdbsim_thread_alive)
	(gdbsim_pid_to_str, gdbsim_has_all_memory, gdbsim_has_memory):
	Refactor as methods of gdbsim_target.
	(gdbsim_ops): Now a gdbsim_target.
	(init_gdbsim_ops): Delete.
	(gdbsim_cntrl_c): Adjust.
	(_initialize_remote_sim): Remove reference to init_gdbsim_ops.

	* amd64-linux-nat.c (amd64_linux_nat_target): New class.
	(the_amd64_linux_nat_target): New.
	(amd64_linux_fetch_inferior_registers)
	(amd64_linux_store_inferior_registers): Refactor as methods of
	amd64_linux_nat_target.
	(_initialize_amd64_linux_nat): Adjust.  Set linux_target.
	* i386-linux-nat.c: Don't include "linux-nat.h".
	(i386_linux_nat_target): New class.
	(the_i386_linux_nat_target): New.
	(i386_linux_fetch_inferior_registers)
	(i386_linux_store_inferior_registers, i386_linux_resume): Refactor
	as methods of i386_linux_nat_target.
	(_initialize_i386_linux_nat): Adjust.  Set linux_target.
	* inf-child.c (inf_child_ops): Delete.
	(inf_child_fetch_inferior_registers)
	(inf_child_store_inferior_registers): Delete.
	(inf_child_post_attach, inf_child_prepare_to_store): Refactor as
	methods of inf_child_target.
	(inf_child_target::supports_terminal_ours)
	(inf_child_target::terminal_init)
	(inf_child_target::terminal_inferior)
	(inf_child_target::terminal_ours_for_output)
	(inf_child_target::terminal_ours, inf_child_target::interrupt)
	(inf_child_target::pass_ctrlc, inf_child_target::terminal_info):
	New.
	(inf_child_open, inf_child_disconnect, inf_child_close)
	(inf_child_mourn_inferior, inf_child_maybe_unpush_target)
	(inf_child_post_startup_inferior, inf_child_can_run)
	(inf_child_pid_to_exec_file): Refactor as methods of
	inf_child_target.
	(inf_child_follow_fork): Delete.
	(inf_child_target::can_create_inferior)
	(inf_child_target::can_attach): New.
	(inf_child_target::has_all_memory, inf_child_target::has_memory)
	(inf_child_target::has_stack, inf_child_target::has_registers)
	(inf_child_target::has_execution): New.
	(inf_child_fileio_open, inf_child_fileio_pwrite)
	(inf_child_fileio_pread, inf_child_fileio_fstat)
	(inf_child_fileio_close, inf_child_fileio_unlink)
	(inf_child_fileio_readlink, inf_child_use_agent)
	(inf_child_can_use_agent): Refactor as methods of
	inf_child_target.
	(return_zero, inf_child_target): Delete.
	(inf_child_target::inf_child_target): New.
	* inf-child.h: Include "target.h".
	(inf_child_target): Delete function prototype.
	(inf_child_target): New class.
	(inf_child_open_target, inf_child_mourn_inferior)
	(inf_child_maybe_unpush_target): Delete.
	* inf-ptrace.c (inf_ptrace_target::~inf_ptrace_target): New.
	(inf_ptrace_follow_fork, inf_ptrace_insert_fork_catchpoint)
	(inf_ptrace_remove_fork_catchpoint, inf_ptrace_create_inferior)
	(inf_ptrace_post_startup_inferior, inf_ptrace_mourn_inferior)
	(inf_ptrace_attach, inf_ptrace_post_attach, inf_ptrace_detach)
	(inf_ptrace_detach_success, inf_ptrace_kill, inf_ptrace_resume)
	(inf_ptrace_wait, inf_ptrace_xfer_partial)
	(inf_ptrace_thread_alive, inf_ptrace_files_info)
	(inf_ptrace_pid_to_str, inf_ptrace_auxv_parse): Refactor as
	methods of inf_ptrace_target.
	(inf_ptrace_target): Delete function.
	* inf-ptrace.h: Include "inf-child.h".
	(inf_ptrace_target): Delete function declaration.
	(inf_ptrace_target): New class.
	(inf_ptrace_trad_target, inf_ptrace_detach_success): Delete.
	* linux-nat.c (linux_target): New.
	(linux_ops, linux_ops_saved, super_xfer_partial): Delete.
	(linux_nat_target::~linux_nat_target): New.
	(linux_child_post_attach, linux_child_post_startup_inferior)
	(linux_child_follow_fork, linux_child_insert_fork_catchpoint)
	(linux_child_remove_fork_catchpoint)
	(linux_child_insert_vfork_catchpoint)
	(linux_child_remove_vfork_catchpoint)
	(linux_child_insert_exec_catchpoint)
	(linux_child_remove_exec_catchpoint)
	(linux_child_set_syscall_catchpoint, linux_nat_pass_signals)
	(linux_nat_create_inferior, linux_nat_attach, linux_nat_detach)
	(linux_nat_resume, linux_nat_stopped_by_watchpoint)
	(linux_nat_stopped_data_address)
	(linux_nat_stopped_by_sw_breakpoint)
	(linux_nat_supports_stopped_by_sw_breakpoint)
	(linux_nat_stopped_by_hw_breakpoint)
	(linux_nat_supports_stopped_by_hw_breakpoint, linux_nat_wait)
	(linux_nat_kill, linux_nat_mourn_inferior)
	(linux_nat_xfer_partial, linux_nat_thread_alive)
	(linux_nat_update_thread_list, linux_nat_pid_to_str)
	(linux_nat_thread_name, linux_child_pid_to_exec_file)
	(linux_child_static_tracepoint_markers_by_strid)
	(linux_nat_is_async_p, linux_nat_can_async_p)
	(linux_nat_supports_non_stop, linux_nat_always_non_stop_p)
	(linux_nat_supports_multi_process)
	(linux_nat_supports_disable_randomization, linux_nat_async)
	(linux_nat_stop, linux_nat_close, linux_nat_thread_address_space)
	(linux_nat_core_of_thread, linux_nat_filesystem_is_local)
	(linux_nat_fileio_open, linux_nat_fileio_readlink)
	(linux_nat_fileio_unlink, linux_nat_thread_events): Refactor as
	methods of linux_nat_target.
	(linux_nat_wait_1, linux_xfer_siginfo, linux_proc_xfer_partial)
	(linux_proc_xfer_spu, linux_nat_xfer_osdata): Remove target_ops
	parameter.
	(check_stopped_by_watchpoint): Adjust.
	(linux_xfer_partial): Delete.
	(linux_target_install_ops, linux_target, linux_nat_add_target):
	Delete.
	(linux_nat_target::linux_nat_target): New.
	* linux-nat.h: Include "inf-ptrace.h".
	(linux_nat_target): New.
	(linux_target, linux_target_install_ops, linux_nat_add_target):
	Delete function declarations.
	(linux_target): Declare global.
	* linux-thread-db.c (thread_db_target): New.
	(thread_db_target::thread_db_target): New.
	(thread_db_ops): Delete.
	(the_thread_db_target): New.
	(thread_db_detach, thread_db_wait, thread_db_mourn_inferior)
	(thread_db_update_thread_list, thread_db_pid_to_str)
	(thread_db_extra_thread_info)
	(thread_db_thread_handle_to_thread_info)
	(thread_db_get_thread_local_address, thread_db_get_ada_task_ptid)
	(thread_db_resume): Refactor as methods of thread_db_target.
	(init_thread_db_ops): Delete.
	(_initialize_thread_db): Remove reference to init_thread_db_ops.
	* x86-linux-nat.c: Don't include "linux-nat.h".
	(super_post_startup_inferior): Delete.
	(x86_linux_nat_target::~x86_linux_nat_target): New.
	(x86_linux_child_post_startup_inferior)
	(x86_linux_read_description, x86_linux_enable_btrace)
	(x86_linux_disable_btrace, x86_linux_teardown_btrace)
	(x86_linux_read_btrace, x86_linux_btrace_conf): Refactor as
	methods of x86_linux_nat_target.
	(x86_linux_create_target): Delete.  Bits folded ...
	(x86_linux_add_target): ... here.  Now takes a linux_nat_target
	pointer.
	* x86-linux-nat.h: Include "linux-nat.h" and "x86-nat.h".
	(x86_linux_nat_target): New class.
	(x86_linux_create_target): Delete.
	(x86_linux_add_target): Now takes a linux_nat_target pointer.
	* x86-nat.c (x86_insert_watchpoint, x86_remove_watchpoint)
	(x86_region_ok_for_watchpoint, x86_stopped_data_address)
	(x86_stopped_by_watchpoint, x86_insert_hw_breakpoint)
	(x86_remove_hw_breakpoint, x86_can_use_hw_breakpoint)
	(x86_stopped_by_hw_breakpoint): Remove target_ops parameter and
	make extern.
	(x86_use_watchpoints): Delete.
	* x86-nat.h: Include "breakpoint.h" and "target.h".
	(x86_use_watchpoints): Delete.
	(x86_can_use_hw_breakpoint, x86_region_ok_for_hw_watchpoint)
	(x86_stopped_by_watchpoint, x86_stopped_data_address)
	(x86_insert_watchpoint, x86_remove_watchpoint)
	(x86_insert_hw_breakpoint, x86_remove_hw_breakpoint)
	(x86_stopped_by_hw_breakpoint): New declarations.
	(x86_nat_target): New template class.

	* ppc-linux-nat.c (ppc_linux_nat_target): New class.
	(the_ppc_linux_nat_target): New.
	(ppc_linux_fetch_inferior_registers)
	(ppc_linux_can_use_hw_breakpoint)
	(ppc_linux_region_ok_for_hw_watchpoint)
	(ppc_linux_ranged_break_num_registers)
	(ppc_linux_insert_hw_breakpoint, ppc_linux_remove_hw_breakpoint)
	(ppc_linux_insert_mask_watchpoint)
	(ppc_linux_remove_mask_watchpoint)
	(ppc_linux_can_accel_watchpoint_condition)
	(ppc_linux_insert_watchpoint, ppc_linux_remove_watchpoint)
	(ppc_linux_stopped_data_address, ppc_linux_stopped_by_watchpoint)
	(ppc_linux_watchpoint_addr_within_range)
	(ppc_linux_masked_watch_num_registers)
	(ppc_linux_store_inferior_registers, ppc_linux_auxv_parse)
	(ppc_linux_read_description): Refactor as methods of
	ppc_linux_nat_target.
	(_initialize_ppc_linux_nat): Adjust.  Set linux_target.

	* procfs.c (procfs_xfer_partial): Delete forward declaration.
	(procfs_target): New class.
	(the_procfs_target): New.
	(procfs_target): Delete function.
	(procfs_auxv_parse, procfs_attach, procfs_detach)
	(procfs_fetch_registers, procfs_store_registers, procfs_wait)
	(procfs_xfer_partial, procfs_resume, procfs_pass_signals)
	(procfs_files_info, procfs_kill_inferior, procfs_mourn_inferior)
	(procfs_create_inferior, procfs_update_thread_list)
	(procfs_thread_alive, procfs_pid_to_str)
	(procfs_can_use_hw_breakpoint, procfs_stopped_by_watchpoint)
	(procfs_stopped_data_address, procfs_insert_watchpoint)
	(procfs_remove_watchpoint, procfs_region_ok_for_hw_watchpoint)
	(proc_find_memory_regions, procfs_info_proc)
	(procfs_make_note_section): Refactor as methods of procfs_target.
	(_initialize_procfs): Adjust.
	* sol-thread.c (sol_thread_target): New class.
	(sol_thread_ops): Now a sol_thread_target.
	(sol_thread_detach, sol_thread_resume, sol_thread_wait)
	(sol_thread_fetch_registers, sol_thread_store_registers)
	(sol_thread_xfer_partial, sol_thread_mourn_inferior)
	(sol_thread_alive, solaris_pid_to_str, sol_update_thread_list)
	(sol_get_ada_task_ptid): Refactor as methods of sol_thread_target.
	(init_sol_thread_ops): Delete.
	(_initialize_sol_thread): Adjust.  Remove references to
	init_sol_thread_ops and complete_target_initialization.

	* windows-nat.c (windows_nat_target): New class.
	(windows_fetch_inferior_registers)
	(windows_store_inferior_registers, windows_resume, windows_wait)
	(windows_attach, windows_detach, windows_pid_to_exec_file)
	(windows_files_info, windows_create_inferior)
	(windows_mourn_inferior, windows_interrupt, windows_kill_inferior)
	(windows_close, windows_pid_to_str, windows_xfer_partial)
	(windows_get_tib_address, windows_get_ada_task_ptid)
	(windows_thread_name, windows_thread_alive): Refactor as
	windows_nat_target methods.
	(do_initial_windows_stuff): Adjust.
	(windows_target): Delete function.
	(_initialize_windows_nat): Adjust.

	* darwin-nat.c (darwin_resume, darwin_wait_to, darwin_interrupt)
	(darwin_mourn_inferior, darwin_kill_inferior)
	(darwin_create_inferior, darwin_attach, darwin_detach)
	(darwin_pid_to_str, darwin_thread_alive, darwin_xfer_partial)
	(darwin_pid_to_exec_file, darwin_get_ada_task_ptid)
	(darwin_supports_multi_process): Refactor as darwin_nat_target
	methods.
	(darwin_resume_to, darwin_files_info): Delete.
	(_initialize_darwin_inferior): Rename to ...
	(_initialize_darwin_nat): ... this.  Adjust to C++ification.
	* darwin-nat.h: Include "inf-child.h".
	(darwin_nat_target): New class.
	(darwin_complete_target): Delete.
	* i386-darwin-nat.c (i386_darwin_nat_target): New class.
	(darwin_target): New.
	(i386_darwin_fetch_inferior_registers)
	(i386_darwin_store_inferior_registers): Refactor as methods of
	darwin_nat_target.
	(darwin_complete_target): Delete, with ...
	(_initialize_i386_darwin_nat): ... bits factored out here.

	* alpha-linux-nat.c (alpha_linux_nat_target): New class.
	(the_alpha_linux_nat_target): New.
	(alpha_linux_register_u_offset): Refactor as
	alpha_linux_nat_target method.
	(_initialize_alpha_linux_nat): Adjust.
	* linux-nat-trad.c (inf_ptrace_register_u_offset): Delete.
	(inf_ptrace_fetch_register, inf_ptrace_fetch_registers)
	(inf_ptrace_store_register, inf_ptrace_store_registers): Refact as
	methods of linux_nat_trad_target.
	(linux_trad_target): Delete.
	* linux-nat-trad.h (linux_trad_target): Delete function.
	(linux_nat_trad_target): New class.
	* mips-linux-nat.c (mips_linux_nat_target): New class.
	(super_fetch_registers, super_store_registers, super_close):
	Delete.
	(the_mips_linux_nat_target): New.
	(mips64_linux_regsets_fetch_registers)
	(mips64_linux_regsets_store_registers)
	(mips64_linux_fetch_registers, mips64_linux_store_registers)
	(mips_linux_register_u_offset, mips_linux_read_description)
	(mips_linux_can_use_hw_breakpoint)
	(mips_linux_stopped_by_watchpoint)
	(mips_linux_stopped_data_address)
	(mips_linux_region_ok_for_hw_watchpoint)
	(mips_linux_insert_watchpoint, mips_linux_remove_watchpoint)
	(mips_linux_close): Refactor as methods of mips_linux_nat.
	(_initialize_mips_linux_nat): Adjust to C++ification.

	* aix-thread.c (aix_thread_target): New class.
	(aix_thread_ops): Now an aix_thread_target.
	(aix_thread_detach, aix_thread_resume, aix_thread_wait)
	(aix_thread_fetch_registers, aix_thread_store_registers)
	(aix_thread_xfer_partial, aix_thread_mourn_inferior)
	(aix_thread_thread_alive, aix_thread_pid_to_str)
	(aix_thread_extra_thread_info, aix_thread_get_ada_task_ptid):
	Refactor as methods of aix_thread_target.
	(init_aix_thread_ops): Delete.
	(_initialize_aix_thread): Remove references to init_aix_thread_ops
	and complete_target_initialization.
	* rs6000-nat.c (rs6000_xfer_shared_libraries): Delete.
	(rs6000_nat_target): New class.
	(the_rs6000_nat_target): New.
	(rs6000_fetch_inferior_registers, rs6000_store_inferior_registers)
	(rs6000_xfer_partial, rs6000_wait, rs6000_create_inferior)
	(rs6000_xfer_shared_libraries): Refactor as rs6000_nat_target methods.
	(super_create_inferior): Delete.
	(_initialize_rs6000_nat): Adjust to C++ification.

	* arm-linux-nat.c (arm_linux_nat_target): New class.
	(the_arm_linux_nat_target): New.
	(arm_linux_fetch_inferior_registers)
	(arm_linux_store_inferior_registers, arm_linux_read_description)
	(arm_linux_can_use_hw_breakpoint, arm_linux_insert_hw_breakpoint)
	(arm_linux_remove_hw_breakpoint)
	(arm_linux_region_ok_for_hw_watchpoint)
	(arm_linux_insert_watchpoint, arm_linux_remove_watchpoint)
	(arm_linux_stopped_data_address, arm_linux_stopped_by_watchpoint)
	(arm_linux_watchpoint_addr_within_range): Refactor as methods of
	arm_linux_nat_target.
	(_initialize_arm_linux_nat): Adjust to C++ification.

	* aarch64-linux-nat.c (aarch64_linux_nat_target): New class.
	(the_aarch64_linux_nat_target): New.
	(aarch64_linux_fetch_inferior_registers)
	(aarch64_linux_store_inferior_registers)
	(aarch64_linux_child_post_startup_inferior)
	(aarch64_linux_read_description)
	(aarch64_linux_can_use_hw_breakpoint)
	(aarch64_linux_insert_hw_breakpoint)
	(aarch64_linux_remove_hw_breakpoint)
	(aarch64_linux_insert_watchpoint, aarch64_linux_remove_watchpoint)
	(aarch64_linux_region_ok_for_hw_watchpoint)
	(aarch64_linux_stopped_data_address)
	(aarch64_linux_stopped_by_watchpoint)
	(aarch64_linux_watchpoint_addr_within_range)
	(aarch64_linux_can_do_single_step): Refactor as methods of
	aarch64_linux_nat_target.
	(super_post_startup_inferior): Delete.
	(_initialize_aarch64_linux_nat): Adjust to C++ification.

	* hppa-linux-nat.c (hppa_linux_nat_target): New class.
	(the_hppa_linux_nat_target): New.
	(hppa_linux_fetch_inferior_registers)
	(hppa_linux_store_inferior_registers): Refactor as methods of
	hppa_linux_nat_target.
	(_initialize_hppa_linux_nat): Adjust to C++ification.

	* ia64-linux-nat.c (ia64_linux_nat_target): New class.
	(the_ia64_linux_nat_target): New.
	(ia64_linux_insert_watchpoint, ia64_linux_remove_watchpoint)
	(ia64_linux_stopped_data_address)
	(ia64_linux_stopped_by_watchpoint, ia64_linux_fetch_registers)
	(ia64_linux_store_registers, ia64_linux_xfer_partial): Refactor as
	ia64_linux_nat_target methods.
	(super_xfer_partial): Delete.
	(_initialize_ia64_linux_nat): Adjust to C++ification.

	* m32r-linux-nat.c (m32r_linux_nat_target): New class.
	(the_m32r_linux_nat_target): New.
	(m32r_linux_fetch_inferior_registers)
	(m32r_linux_store_inferior_registers): Refactor as
	m32r_linux_nat_target methods.
	(_initialize_m32r_linux_nat): Adjust to C++ification.

	* m68k-linux-nat.c (m68k_linux_nat_target): New class.
	(the_m68k_linux_nat_target): New.
	(m68k_linux_fetch_inferior_registers)
	(m68k_linux_store_inferior_registers): Refactor as
	m68k_linux_nat_target methods.
	(_initialize_m68k_linux_nat): Adjust to C++ification.

	* s390-linux-nat.c (s390_linux_nat_target): New class.
	(the_s390_linux_nat_target): New.
	(s390_linux_fetch_inferior_registers)
	(s390_linux_store_inferior_registers, s390_stopped_by_watchpoint)
	(s390_insert_watchpoint, s390_remove_watchpoint)
	(s390_can_use_hw_breakpoint, s390_insert_hw_breakpoint)
	(s390_remove_hw_breakpoint, s390_region_ok_for_hw_watchpoint)
	(s390_auxv_parse, s390_read_description): Refactor as methods of
	s390_linux_nat_target.
	(_initialize_s390_nat): Adjust to C++ification.

	* sparc-linux-nat.c (sparc_linux_nat_target): New class.
	(the_sparc_linux_nat_target): New.
	(_initialize_sparc_linux_nat): Adjust to C++ification.
	* sparc-nat.c (sparc_fetch_inferior_registers)
	(sparc_store_inferior_registers): Remove target_ops parameter.
	* sparc-nat.h (sparc_fetch_inferior_registers)
	(sparc_store_inferior_registers): Remove target_ops parameter.
	* sparc64-linux-nat.c (sparc64_linux_nat_target): New class.
	(the_sparc64_linux_nat_target): New.
	(_initialize_sparc64_linux_nat): Adjust to C++ification.

	* spu-linux-nat.c (spu_linux_nat_target): New class.
	(the_spu_linux_nat_target): New.
	(spu_child_post_startup_inferior, spu_child_post_attach)
	(spu_child_wait, spu_fetch_inferior_registers)
	(spu_store_inferior_registers, spu_xfer_partial)
	(spu_can_use_hw_breakpoint): Refactor as spu_linux_nat_target
	methods.
	(_initialize_spu_nat): Adjust to C++ification.

	* tilegx-linux-nat.c (tilegx_linux_nat_target): New class.
	(the_tilegx_linux_nat_target): New.
	(fetch_inferior_registers, store_inferior_registers):
	Refactor as methods.
	(_initialize_tile_linux_nat): Adjust to C++ification.

	* xtensa-linux-nat.c (xtensa_linux_nat_target): New class.
	(the_xtensa_linux_nat_target): New.
	(xtensa_linux_fetch_inferior_registers)
	(xtensa_linux_store_inferior_registers): Refactor as
	xtensa_linux_nat_target methods.
	(_initialize_xtensa_linux_nat): Adjust to C++ification.

	* fbsd-nat.c (USE_SIGTRAP_SIGINFO): Delete.
	(fbsd_pid_to_exec_file, fbsd_find_memory_regions)
	(fbsd_find_memory_regions, fbsd_info_proc, fbsd_xfer_partial)
	(fbsd_thread_alive, fbsd_pid_to_str, fbsd_thread_name)
	(fbsd_update_thread_list, fbsd_resume, fbsd_wait)
	(fbsd_stopped_by_sw_breakpoint)
	(fbsd_supports_stopped_by_sw_breakpoint, fbsd_follow_fork)
	(fbsd_insert_fork_catchpoint, fbsd_remove_fork_catchpoint)
	(fbsd_insert_vfork_catchpoint, fbsd_remove_vfork_catchpoint)
	(fbsd_post_startup_inferior, fbsd_post_attach)
	(fbsd_insert_exec_catchpoint, fbsd_remove_exec_catchpoint)
	(fbsd_set_syscall_catchpoint)
	(super_xfer_partial, super_resume, super_wait)
	(fbsd_supports_stopped_by_hw_breakpoint): Delete.
	(fbsd_handle_debug_trap): Remove target_ops parameter.
	(fbsd_nat_add_target): Delete.
	* fbsd-nat.h: Include "inf-ptrace.h".
	(fbsd_nat_add_target): Delete.
	(USE_SIGTRAP_SIGINFO): Define.
	(fbsd_nat_target): New class.

	* amd64-bsd-nat.c (amd64bsd_fetch_inferior_registers)
	(amd64bsd_store_inferior_registers): Remove target_ops parameter.
	(amd64bsd_target): Delete.
	* amd64-bsd-nat.h: New file.
	* amd64-fbsd-nat.c: Include "amd64-bsd-nat.h" instead of
	"x86-bsd-nat.h".
	(amd64_fbsd_nat_target): New class.
	(the_amd64_fbsd_nat_target): New.
	(amd64fbsd_read_description): Refactor as method of
	amd64_fbsd_nat_target.
	(amd64_fbsd_nat_target::supports_stopped_by_hw_breakpoint): New.
	(_initialize_amd64fbsd_nat): Adjust to C++ification.
	* amd64-nat.h (amd64bsd_target): Delete function declaration.
	* i386-bsd-nat.c (i386bsd_fetch_inferior_registers)
	(i386bsd_store_inferior_registers): Remove target_ops parameter.
	(i386bsd_target): Delete.
	* i386-bsd-nat.h (i386bsd_target): Delete function declaration.
	(i386bsd_fetch_inferior_registers)
	(i386bsd_store_inferior_registers): Declare.
	(i386_bsd_nat_target): New class.
	* i386-fbsd-nat.c (i386_fbsd_nat_target): New class.
	(the_i386_fbsd_nat_target): New.
	(i386fbsd_resume, i386fbsd_read_description): Refactor as
	i386_fbsd_nat_target methods.
	(i386_fbsd_nat_target::supports_stopped_by_hw_breakpoint): New.
	(_initialize_i386fbsd_nat): Adjust to C++ification.
	* x86-bsd-nat.c (super_mourn_inferior): Delete.
	(x86bsd_mourn_inferior, x86bsd_target): Delete.
	(_initialize_x86_bsd_nat): Adjust to C++ification.
	* x86-bsd-nat.h: Include "x86-nat.h".
	(x86bsd_target): Delete declaration.
	(x86bsd_nat_target): New class.

	* aarch64-fbsd-nat.c (aarch64_fbsd_nat_target): New class.
	(the_aarch64_fbsd_nat_target): New.
	(aarch64_fbsd_fetch_inferior_registers)
	(aarch64_fbsd_store_inferior_registers): Refactor as methods of
	aarch64_fbsd_nat_target.
	(_initialize_aarch64_fbsd_nat): Adjust to C++ification.
	* alpha-bsd-nat.c (alpha_bsd_nat_target): New class.
	(the_alpha_bsd_nat_target): New.
	(alphabsd_fetch_inferior_registers)
	(alphabsd_store_inferior_registers): Refactor as
	alpha_bsd_nat_target methods.
	(_initialize_alphabsd_nat): Refactor as methods of
	alpha_bsd_nat_target.
	* amd64-nbsd-nat.c: Include "amd64-bsd-nat.h".
	(the_amd64_nbsd_nat_target): New.
	(_initialize_amd64nbsd_nat): Adjust to C++ification.
	* amd64-obsd-nat.c: Include "amd64-bsd-nat.h".
	(the_amd64_obsd_nat_target): New.
	(_initialize_amd64obsd_nat): Adjust to C++ification.
	* arm-fbsd-nat.c (arm_fbsd_nat_target): New.
	(the_arm_fbsd_nat_target): New.
	(arm_fbsd_fetch_inferior_registers)
	(arm_fbsd_store_inferior_registers, arm_fbsd_read_description):
	(_initialize_arm_fbsd_nat): Refactor as methods of
	arm_fbsd_nat_target.
	(_initialize_arm_fbsd_nat): Adjust to C++ification.
	* arm-nbsd-nat.c (arm_netbsd_nat_target): New class.
	(the_arm_netbsd_nat_target): New.
	(armnbsd_fetch_registers, armnbsd_store_registers): Refactor as
	arm_netbsd_nat_target.
	(_initialize_arm_netbsd_nat): Adjust to C++ification.
	* hppa-nbsd-nat.c (hppa_nbsd_nat_target): New class.
	(the_hppa_nbsd_nat_target): New.
	(hppanbsd_fetch_registers, hppanbsd_store_registers): Refactor as
	hppa_nbsd_nat_target methods.
	(_initialize_hppanbsd_nat): Adjust to C++ification.
	* hppa-obsd-nat.c (hppa_obsd_nat_target): New class.
	(the_hppa_obsd_nat_target): New.
	(hppaobsd_fetch_registers, hppaobsd_store_registers): Refactor as
	methods of hppa_obsd_nat_target.
	(_initialize_hppaobsd_nat): Adjust to C++ification.  Use
	add_target.
	* i386-nbsd-nat.c (the_i386_nbsd_nat_target): New.
	(_initialize_i386nbsd_nat): Adjust to C++ification.  Use
	add_target.
	* i386-obsd-nat.c (the_i386_obsd_nat_target): New.
	(_initialize_i386obsd_nat): Use add_target.
	* m68k-bsd-nat.c (m68k_bsd_nat_target): New class.
	(the_m68k_bsd_nat_target): New.
	(m68kbsd_fetch_inferior_registers)
	(m68kbsd_store_inferior_registers): Refactor as methods of
	m68k_bsd_nat_target.
	(_initialize_m68kbsd_nat): Adjust to C++ification.
	* mips-fbsd-nat.c (mips_fbsd_nat_target): New class.
	(the_mips_fbsd_nat_target): New.
	(mips_fbsd_fetch_inferior_registers)
	(mips_fbsd_store_inferior_registers): Refactor as methods of
	mips_fbsd_nat_target.
	(_initialize_mips_fbsd_nat): Adjust to C++ification.  Use
	add_target.
	* mips-nbsd-nat.c (mips_nbsd_nat_target): New class.
	(the_mips_nbsd_nat_target): New.
	(mipsnbsd_fetch_inferior_registers)
	(mipsnbsd_store_inferior_registers): Refactor as methods of
	mips_nbsd_nat_target.
	(_initialize_mipsnbsd_nat): Adjust to C++ification.
	* mips64-obsd-nat.c (mips64_obsd_nat_target): New class.
	(the_mips64_obsd_nat_target): New.
	(mips64obsd_fetch_inferior_registers)
	(mips64obsd_store_inferior_registers): Refactor as methods of
	mips64_obsd_nat_target.
	(_initialize_mips64obsd_nat): Adjust to C++ification.  Use
	add_target.
	* nbsd-nat.c (nbsd_pid_to_exec_file): Refactor as method of
	nbsd_nat_target.
	* nbsd-nat.h: Include "inf-ptrace.h".
	(nbsd_nat_target): New class.
	* obsd-nat.c (obsd_pid_to_str, obsd_update_thread_list)
	(obsd_wait): Refactor as methods of obsd_nat_target.
	(obsd_add_target): Delete.
	* obsd-nat.h: Include "inf-ptrace.h".
	(obsd_nat_target): New class.
	* ppc-fbsd-nat.c (ppc_fbsd_nat_target): New class.
	(the_ppc_fbsd_nat_target): New.
	(ppcfbsd_fetch_inferior_registers)
	(ppcfbsd_store_inferior_registers): Refactor as methods of
	ppc_fbsd_nat_target.
	(_initialize_ppcfbsd_nat): Adjust to C++ification.  Use
	add_target.
	* ppc-nbsd-nat.c (ppc_nbsd_nat_target): New class.
	(the_ppc_nbsd_nat_target): New.
	(ppcnbsd_fetch_inferior_registers)
	(ppcnbsd_store_inferior_registers): Refactor as methods of
	ppc_nbsd_nat_target.
	(_initialize_ppcnbsd_nat): Adjust to C++ification.
	* ppc-obsd-nat.c (ppc_obsd_nat_target): New class.
	(the_ppc_obsd_nat_target): New.
	(ppcobsd_fetch_registers, ppcobsd_store_registers): Refactor as
	methods of ppc_obsd_nat_target.
	(_initialize_ppcobsd_nat): Adjust to C++ification.  Use
	add_target.
	* sh-nbsd-nat.c (sh_nbsd_nat_target): New class.
	(the_sh_nbsd_nat_target): New.
	(shnbsd_fetch_inferior_registers)
	(shnbsd_store_inferior_registers): Refactor as methods of
	sh_nbsd_nat_target.
	(_initialize_shnbsd_nat): Adjust to C++ification.
	* sparc-nat.c (sparc_xfer_wcookie): Make extern.
	(inf_ptrace_xfer_partial): Delete.
	(sparc_xfer_partial, sparc_target): Delete.
	* sparc-nat.h (sparc_fetch_inferior_registers)
	(sparc_store_inferior_registers, sparc_xfer_wcookie): Declare.
	(sparc_target): Delete function declaration.
	(sparc_target): New template class.
	* sparc-nbsd-nat.c (the_sparc_nbsd_nat_target): New.
	(_initialize_sparcnbsd_nat): Adjust to C++ification.
	* sparc64-fbsd-nat.c (the_sparc64_fbsd_nat_target): New.
	(_initialize_sparc64fbsd_nat): Adjust to C++ification.  Use
	add_target.
	* sparc64-nbsd-nat.c (the_sparc64_nbsd_nat_target): New.
	(_initialize_sparc64nbsd_nat): Adjust to C++ification.
	* sparc64-obsd-nat.c (the_sparc64_obsd_nat_target): New.
	(_initialize_sparc64obsd_nat): Adjust to C++ification.  Use
	add_target.
	* vax-bsd-nat.c (vax_bsd_nat_target): New class.
	(the_vax_bsd_nat_target): New.
	(vaxbsd_fetch_inferior_registers)
	(vaxbsd_store_inferior_registers): Refactor as vax_bsd_nat_target
	methods.
	(_initialize_vaxbsd_nat): Adjust to C++ification.

	* bsd-kvm.c (bsd_kvm_target): New class.
	(bsd_kvm_ops): Now a bsd_kvm_target.
	(bsd_kvm_open, bsd_kvm_close, bsd_kvm_xfer_partial)
	(bsd_kvm_files_info, bsd_kvm_fetch_registers)
	(bsd_kvm_thread_alive, bsd_kvm_pid_to_str): Refactor as methods of
	bsd_kvm_target.
	(bsd_kvm_return_one): Delete.
	(bsd_kvm_add_target): Adjust to C++ification.

	* nto-procfs.c (nto_procfs_target, nto_procfs_target_native)
	(nto_procfs_target_procfs): New classes.
	(procfs_open_1, procfs_thread_alive, procfs_update_thread_list)
	(procfs_files_info, procfs_pid_to_exec_file, procfs_attach)
	(procfs_post_attach, procfs_wait, procfs_fetch_registers)
	(procfs_xfer_partial, procfs_detach, procfs_insert_breakpoint)
	(procfs_remove_breakpoint, procfs_insert_hw_breakpoint)
	(procfs_remove_hw_breakpoint, procfs_resume)
	(procfs_mourn_inferior, procfs_create_inferior, procfs_interrupt)
	(procfs_kill_inferior, procfs_store_registers)
	(procfs_pass_signals, procfs_pid_to_str, procfs_can_run): Refactor
	as methods of nto_procfs_target.
	(nto_procfs_ops): Now an nto_procfs_target_procfs.
	(nto_native_ops): Delete.
	(procfs_open, procfs_native_open): Delete.
	(nto_native_ops): Now an nto_procfs_target_native.
	(init_procfs_targets): Adjust to C++ification.
	(procfs_can_use_hw_breakpoint, procfs_remove_hw_watchpoint)
	(procfs_insert_hw_watchpoint, procfs_stopped_by_watchpoint):
	Refactor as methods of nto_procfs_target.

	* go32-nat.c (go32_nat_target): New class.
	(the_go32_nat_target): New.
	(go32_attach, go32_resume, go32_wait, go32_fetch_registers)
	(go32_store_registers, go32_xfer_partial, go32_files_info)
	(go32_kill_inferior, go32_create_inferior, go32_mourn_inferior)
	(go32_terminal_init, go32_terminal_info, go32_terminal_inferior)
	(go32_terminal_ours, go32_pass_ctrlc, go32_thread_alive)
	(go32_pid_to_str): Refactor as methods of go32_nat_target.
	(go32_target): Delete.
	(_initialize_go32_nat): Adjust to C++ification.

	* gnu-nat.c (gnu_wait, gnu_resume, gnu_kill_inferior)
	(gnu_mourn_inferior, gnu_create_inferior, gnu_attach, gnu_detach)
	(gnu_stop, gnu_thread_alive, gnu_xfer_partial)
	(gnu_find_memory_regions, gnu_pid_to_str): Refactor as methods of
	gnu_nat_target.
	(gnu_target): Delete.
	* gnu-nat.h (gnu_target): Delete.
	(gnu_nat_target): New class.
	* i386-gnu-nat.c (gnu_base_target): New.
	(i386_gnu_nat_target): New class.
	(the_i386_gnu_nat_target): New.
	(_initialize_i386gnu_nat): Adjust to C++ification.

gdb/testsuite/ChangeLog:
2018-05-02  Pedro Alves  <palves@redhat.com>

	* gdb.base/breakpoint-in-ro-region.exp: Adjust to to_resume and
	to_log_command renames.
	* gdb.base/sss-bp-on-user-bp-2.exp: Likewise.
This commit is contained in:
Pedro Alves 2018-05-03 00:37:22 +01:00
parent 3fffc0701a
commit f6ac5f3d63
151 changed files with 10134 additions and 9210 deletions

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,14 @@
#include "aarch64-fbsd-tdep.h"
#include "inf-ptrace.h"
struct aarch64_fbsd_nat_target final : public fbsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static aarch64_fbsd_nat_target the_aarch64_fbsd_nat_target;
/* Determine if PT_GETREGS fetches REGNUM. */
static bool
@ -48,9 +56,9 @@ getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
aarch64_fbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
aarch64_fbsd_nat_target::fetch_registers (struct regcache *regcache,
int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -81,9 +89,9 @@ aarch64_fbsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
static void
aarch64_fbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
aarch64_fbsd_nat_target::store_registers (struct regcache *regcache,
int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -120,10 +128,5 @@ aarch64_fbsd_store_inferior_registers (struct target_ops *ops,
void
_initialize_aarch64_fbsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = aarch64_fbsd_fetch_inferior_registers;
t->to_store_registers = aarch64_fbsd_store_inferior_registers;
fbsd_nat_add_target (t);
add_target (&the_aarch64_fbsd_nat_target);
}

View File

@ -49,6 +49,36 @@
#define TRAP_HWBKPT 0x0004
#endif
class aarch64_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
const struct target_desc *read_description () override;
/* Add our hardware breakpoint and watchpoint implementation. */
int can_use_hw_breakpoint (enum bptype, int, int) override;
int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
int can_do_single_step () override;
/* Override the GNU/Linux inferior startup hook. */
void post_startup_inferior (ptid_t) override;
};
static aarch64_linux_nat_target the_aarch64_linux_nat_target;
/* Per-process data. We don't bind this to a per-inferior registry
because of targets like x86 GNU/Linux that need to keep track of
processes that aren't bound to any inferior (e.g., fork children,
@ -342,12 +372,11 @@ store_fpregs_to_thread (const struct regcache *regcache)
}
}
/* Implement the "to_fetch_register" target_ops method. */
/* Implement the "fetch_registers" target_ops method. */
static void
aarch64_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache,
int regno)
void
aarch64_linux_nat_target::fetch_registers (struct regcache *regcache,
int regno)
{
if (regno == -1)
{
@ -360,12 +389,11 @@ aarch64_linux_fetch_inferior_registers (struct target_ops *ops,
fetch_fpregs_from_thread (regcache);
}
/* Implement the "to_store_register" target_ops method. */
/* Implement the "store_registers" target_ops method. */
static void
aarch64_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache,
int regno)
void
aarch64_linux_nat_target::store_registers (struct regcache *regcache,
int regno)
{
if (regno == -1)
{
@ -467,26 +495,22 @@ ps_get_thread_area (struct ps_prochandle *ph,
}
static void (*super_post_startup_inferior) (struct target_ops *self,
ptid_t ptid);
/* Implement the "post_startup_inferior" target_ops method. */
/* Implement the "to_post_startup_inferior" target_ops method. */
static void
aarch64_linux_child_post_startup_inferior (struct target_ops *self,
ptid_t ptid)
void
aarch64_linux_nat_target::post_startup_inferior (ptid_t ptid)
{
aarch64_forget_process (ptid_get_pid (ptid));
aarch64_linux_get_debug_reg_capacity (ptid_get_pid (ptid));
super_post_startup_inferior (self, ptid);
linux_nat_target::post_startup_inferior (ptid);
}
extern struct target_desc *tdesc_arm_with_neon;
/* Implement the "to_read_description" target_ops method. */
/* Implement the "read_description" target_ops method. */
static const struct target_desc *
aarch64_linux_read_description (struct target_ops *ops)
const struct target_desc *
aarch64_linux_nat_target::read_description ()
{
int ret, tid;
gdb_byte regbuf[VFP_REGS_SIZE];
@ -542,10 +566,9 @@ aarch64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
one). OTHERTYPE is non-zero if other types of watchpoints are
currently enabled. */
static int
aarch64_linux_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type,
int cnt, int othertype)
int
aarch64_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
int cnt, int othertype)
{
if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
|| type == bp_access_watchpoint || type == bp_watchpoint)
@ -573,10 +596,9 @@ aarch64_linux_can_use_hw_breakpoint (struct target_ops *self,
/* Insert a hardware-assisted breakpoint at BP_TGT->reqstd_address.
Return 0 on success, -1 on failure. */
static int
aarch64_linux_insert_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
aarch64_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
int ret;
CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address;
@ -607,10 +629,9 @@ aarch64_linux_insert_hw_breakpoint (struct target_ops *self,
/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address.
Return 0 on success, -1 on failure. */
static int
aarch64_linux_remove_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
aarch64_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
int ret;
CORE_ADDR addr = bp_tgt->placed_address;
@ -637,17 +658,16 @@ aarch64_linux_remove_hw_breakpoint (struct target_ops *self,
return ret;
}
/* Implement the "to_insert_watchpoint" target_ops method.
/* Implement the "insert_watchpoint" target_ops method.
Insert a watchpoint to watch a memory region which starts at
address ADDR and whose length is LEN bytes. Watch memory accesses
of the type TYPE. Return 0 on success, -1 on failure. */
static int
aarch64_linux_insert_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
aarch64_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
int ret;
struct aarch64_debug_reg_state *state
@ -671,16 +691,15 @@ aarch64_linux_insert_watchpoint (struct target_ops *self,
return ret;
}
/* Implement the "to_remove_watchpoint" target_ops method.
/* Implement the "remove_watchpoint" target_ops method.
Remove a watchpoint that watched the memory region which starts at
address ADDR, whose length is LEN bytes, and for accesses of the
type TYPE. Return 0 on success, -1 on failure. */
static int
aarch64_linux_remove_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
aarch64_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
int ret;
struct aarch64_debug_reg_state *state
@ -704,20 +723,18 @@ aarch64_linux_remove_watchpoint (struct target_ops *self,
return ret;
}
/* Implement the "to_region_ok_for_hw_watchpoint" target_ops method. */
/* Implement the "region_ok_for_hw_watchpoint" target_ops method. */
static int
aarch64_linux_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len)
int
aarch64_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
return aarch64_linux_region_ok_for_watchpoint (addr, len);
}
/* Implement the "to_stopped_data_address" target_ops method. */
/* Implement the "stopped_data_address" target_ops method. */
static int
aarch64_linux_stopped_data_address (struct target_ops *target,
CORE_ADDR *addr_p)
int
aarch64_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
{
siginfo_t siginfo;
int i, tid;
@ -752,30 +769,29 @@ aarch64_linux_stopped_data_address (struct target_ops *target,
return 0;
}
/* Implement the "to_stopped_by_watchpoint" target_ops method. */
/* Implement the "stopped_by_watchpoint" target_ops method. */
static int
aarch64_linux_stopped_by_watchpoint (struct target_ops *ops)
int
aarch64_linux_nat_target::stopped_by_watchpoint ()
{
CORE_ADDR addr;
return aarch64_linux_stopped_data_address (ops, &addr);
return stopped_data_address (&addr);
}
/* Implement the "to_watchpoint_addr_within_range" target_ops method. */
/* Implement the "watchpoint_addr_within_range" target_ops method. */
static int
aarch64_linux_watchpoint_addr_within_range (struct target_ops *target,
CORE_ADDR addr,
CORE_ADDR start, int length)
int
aarch64_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
CORE_ADDR start, int length)
{
return start <= addr && start + length - 1 >= addr;
}
/* Implement the "to_can_do_single_step" target_ops method. */
/* Implement the "can_do_single_step" target_ops method. */
static int
aarch64_linux_can_do_single_step (struct target_ops *target)
int
aarch64_linux_nat_target::can_do_single_step ()
{
return 1;
}
@ -804,38 +820,13 @@ triggers a breakpoint or watchpoint."),
void
_initialize_aarch64_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
struct target_ops *t = &the_aarch64_linux_nat_target;
add_show_debug_regs_command ();
/* Add our register access methods. */
t->to_fetch_registers = aarch64_linux_fetch_inferior_registers;
t->to_store_registers = aarch64_linux_store_inferior_registers;
t->to_read_description = aarch64_linux_read_description;
t->to_can_use_hw_breakpoint = aarch64_linux_can_use_hw_breakpoint;
t->to_insert_hw_breakpoint = aarch64_linux_insert_hw_breakpoint;
t->to_remove_hw_breakpoint = aarch64_linux_remove_hw_breakpoint;
t->to_region_ok_for_hw_watchpoint =
aarch64_linux_region_ok_for_hw_watchpoint;
t->to_insert_watchpoint = aarch64_linux_insert_watchpoint;
t->to_remove_watchpoint = aarch64_linux_remove_watchpoint;
t->to_stopped_by_watchpoint = aarch64_linux_stopped_by_watchpoint;
t->to_stopped_data_address = aarch64_linux_stopped_data_address;
t->to_watchpoint_addr_within_range =
aarch64_linux_watchpoint_addr_within_range;
t->to_can_do_single_step = aarch64_linux_can_do_single_step;
/* Override the GNU/Linux inferior startup hook. */
super_post_startup_inferior = t->to_post_startup_inferior;
t->to_post_startup_inferior = aarch64_linux_child_post_startup_inferior;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_aarch64_linux_nat_target;
add_target (t);
linux_nat_set_new_thread (t, aarch64_linux_new_thread);
linux_nat_set_delete_thread (t, aarch64_linux_delete_thread);
linux_nat_set_new_fork (t, aarch64_linux_new_fork);

View File

@ -108,7 +108,45 @@ struct pd_thread {
/* This module's target-specific operations, active while pd_able is true. */
static struct target_ops aix_thread_ops;
class aix_thread_target final : public target_ops
{
public:
aix_thread_target ()
{ to_stratum = thread_stratum; }
const char *shortname () override
{ return "aix-threads"; }
const char *longname () override
{ return _("AIX pthread support"); }
const char *doc () override
{ return _("AIX pthread support"); }
void detach (inferior *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void mourn_inferior () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
const char *extra_thread_info (struct thread_info *) override;
ptid_t get_ada_task_ptid (long lwp, long thread) override;
};
static aix_thread_target aix_thread_ops;
/* Address of the function that libpthread will call when libpthdebug
is ready to be initialized. */
@ -980,21 +1018,20 @@ aix_thread_inferior_created (struct target_ops *ops, int from_tty)
/* Detach from the process attached to by aix_thread_attach(). */
static void
aix_thread_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
aix_thread_target::detach (inferior *inf, int from_tty)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
pd_disable ();
beneath->to_detach (beneath, inf, from_tty);
beneath->detach (inf, from_tty);
}
/* Tell the inferior process to continue running thread PID if != -1
and all threads otherwise. */
static void
aix_thread_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal sig)
void
aix_thread_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
{
struct thread_info *thread;
pthdb_tid_t tid[2];
@ -1002,10 +1039,10 @@ aix_thread_resume (struct target_ops *ops,
if (!PD_TID (ptid))
{
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
inferior_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
beneath->to_resume (beneath, ptid, step, sig);
beneath->resume (ptid, step, sig);
}
else
{
@ -1035,11 +1072,11 @@ aix_thread_resume (struct target_ops *ops,
If an error occurs, return -1, else return the pid of the stopped
thread. */
static ptid_t
aix_thread_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
aix_thread_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
{
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
@ -1047,7 +1084,7 @@ aix_thread_wait (struct target_ops *ops,
pid_to_prc (&ptid);
inferior_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
ptid = beneath->to_wait (beneath, ptid, status, options);
ptid = beneath->wait (ptid, status, options);
}
if (ptid_get_pid (ptid) == -1)
@ -1319,16 +1356,15 @@ fetch_regs_kernel_thread (struct regcache *regcache, int regno,
/* Fetch register REGNO if != -1 or all registers otherwise from the
thread/process connected to REGCACHE. */
static void
aix_thread_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
aix_thread_target::fetch_registers (struct regcache *regcache, int regno)
{
struct thread_info *thread;
pthdb_tid_t tid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
if (!PD_TID (regcache_get_ptid (regcache)))
beneath->to_fetch_registers (beneath, regcache, regno);
beneath->fetch_registers (regcache, regno);
else
{
thread = find_thread_ptid (regcache_get_ptid (regcache));
@ -1674,16 +1710,15 @@ store_regs_kernel_thread (const struct regcache *regcache, int regno,
/* Store gdb's current view of the register set into the
thread/process connected to REGCACHE. */
static void
aix_thread_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
aix_thread_target::store_registers (struct regcache *regcache, int regno)
{
struct thread_info *thread;
pthdb_tid_t tid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
if (!PD_TID (regcache_get_ptid (regcache)))
beneath->to_store_registers (beneath, regcache, regno);
beneath->store_registers (regcache, regno);
else
{
thread = find_thread_ptid (regcache_get_ptid (regcache));
@ -1699,40 +1734,41 @@ aix_thread_store_registers (struct target_ops *ops,
/* Implement the to_xfer_partial target_ops method. */
static enum target_xfer_status
aix_thread_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
aix_thread_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
inferior_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
return beneath->to_xfer_partial (beneath, object, annex, readbuf,
writebuf, offset, len, xfered_len);
return beneath->xfer_partial (object, annex, readbuf,
writebuf, offset, len, xfered_len);
}
/* Clean up after the inferior exits. */
static void
aix_thread_mourn_inferior (struct target_ops *ops)
void
aix_thread_target::mourn_inferior ()
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
pd_deactivate ();
beneath->to_mourn_inferior (beneath);
beneath->mourn_inferior ();
}
/* Return whether thread PID is still valid. */
static int
aix_thread_thread_alive (struct target_ops *ops, ptid_t ptid)
int
aix_thread_target::thread_alive (ptid_t ptid)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
if (!PD_TID (ptid))
return beneath->to_thread_alive (beneath, ptid);
return beneath->thread_alive (ptid);
/* We update the thread list every time the child stops, so all
valid threads should be in the thread list. */
@ -1742,14 +1778,14 @@ aix_thread_thread_alive (struct target_ops *ops, ptid_t ptid)
/* Return a printable representation of composite PID for use in
"info threads" output. */
static const char *
aix_thread_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
aix_thread_target::pid_to_str (ptid_t ptid)
{
static char *ret = NULL;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
if (!PD_TID (ptid))
return beneath->to_pid_to_str (beneath, ptid);
return beneath->pid_to_str (ptid);
/* Free previous return value; a new one will be allocated by
xstrprintf(). */
@ -1762,9 +1798,8 @@ aix_thread_pid_to_str (struct target_ops *ops, ptid_t ptid)
/* Return a printable representation of extra information about
THREAD, for use in "info threads" output. */
static const char *
aix_thread_extra_thread_info (struct target_ops *self,
struct thread_info *thread)
const char *
aix_thread_target::extra_thread_info (struct thread_info *thread)
{
int status;
pthdb_pthread_t pdtid;
@ -1819,35 +1854,12 @@ aix_thread_extra_thread_info (struct target_ops *self,
return ret;
}
static ptid_t
aix_thread_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
ptid_t
aix_thread_target::get_ada_task_ptid (long lwp, long thread)
{
return ptid_build (ptid_get_pid (inferior_ptid), 0, thread);
}
/* Initialize target aix_thread_ops. */
static void
init_aix_thread_ops (void)
{
aix_thread_ops.to_shortname = "aix-threads";
aix_thread_ops.to_longname = _("AIX pthread support");
aix_thread_ops.to_doc = _("AIX pthread support");
aix_thread_ops.to_detach = aix_thread_detach;
aix_thread_ops.to_resume = aix_thread_resume;
aix_thread_ops.to_wait = aix_thread_wait;
aix_thread_ops.to_fetch_registers = aix_thread_fetch_registers;
aix_thread_ops.to_store_registers = aix_thread_store_registers;
aix_thread_ops.to_xfer_partial = aix_thread_xfer_partial;
aix_thread_ops.to_mourn_inferior = aix_thread_mourn_inferior;
aix_thread_ops.to_thread_alive = aix_thread_thread_alive;
aix_thread_ops.to_pid_to_str = aix_thread_pid_to_str;
aix_thread_ops.to_extra_thread_info = aix_thread_extra_thread_info;
aix_thread_ops.to_get_ada_task_ptid = aix_thread_get_ada_task_ptid;
aix_thread_ops.to_stratum = thread_stratum;
aix_thread_ops.to_magic = OPS_MAGIC;
}
/* Module startup initialization function, automagically called by
init.c. */
@ -1855,9 +1867,6 @@ init_aix_thread_ops (void)
void
_initialize_aix_thread (void)
{
init_aix_thread_ops ();
complete_target_initialization (&aix_thread_ops);
/* Notice when object files get loaded and unloaded. */
gdb::observers::new_objfile.attach (new_objfile);

View File

@ -43,6 +43,14 @@ typedef struct fpreg fpregset_t;
#include "gregset.h"
struct alpha_bsd_nat_target final : public inf_ptrace_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static alpha_bsd_nat_target the_alpha_bsd_nat_target;
/* Provide *regset() wrappers around the generic Alpha BSD register
supply/fill routines. */
@ -83,9 +91,8 @@ getregs_supplies (int regno)
/* Fetch register REGNO from the inferior. If REGNO is -1, do this
for all registers (including the floating point registers). */
static void
alphabsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
alpha_bsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
if (regno == -1 || getregs_supplies (regno))
{
@ -116,9 +123,8 @@ alphabsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNO back into the inferior. If REGNO is -1, do
this for all registers (including the floating point registers). */
static void
alphabsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
alpha_bsd_nat_target::store_registers (struct regcache *regcache, int regno)
{
if (regno == -1 || getregs_supplies (regno))
{
@ -190,12 +196,7 @@ alphabsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
void
_initialize_alphabsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = alphabsd_fetch_inferior_registers;
t->to_store_registers = alphabsd_store_inferior_registers;
add_target (t);
add_target (&the_alpha_bsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (alphabsd_supply_pcb);

View File

@ -32,6 +32,15 @@
/* The address of UNIQUE for ptrace. */
#define ALPHA_UNIQUE_PTRACE_ADDR 65
class alpha_linux_nat_target final : public linux_nat_trad_target
{
protected:
/* Override linux_nat_trad_target methods. */
CORE_ADDR register_u_offset (struct gdbarch *gdbarch,
int regno, int store_p) override;
};
static alpha_linux_nat_target the_alpha_linux_nat_target;
/* See the comment in m68k-tdep.c regarding the utility of these
functions. */
@ -77,9 +86,9 @@ fill_fpregset (const struct regcache *regcache,
alpha_fill_fp_regs (regcache, regno, regp, regp + 31);
}
static CORE_ADDR
alpha_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
CORE_ADDR
alpha_linux_nat_target::register_u_offset (struct gdbarch *gdbarch,
int regno, int store_p)
{
if (regno == gdbarch_pc_regnum (gdbarch))
return PC;
@ -94,5 +103,6 @@ alpha_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
void
_initialize_alpha_linux_nat (void)
{
linux_nat_add_target (linux_trad_target (alpha_linux_register_u_offset));
linux_target = &the_alpha_linux_nat_target;
add_target (&the_alpha_linux_nat_target);
}

View File

@ -38,9 +38,8 @@
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers (including the floating-point registers). */
static void
amd64bsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
amd64bsd_fetch_inferior_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -112,9 +111,8 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating-point registers). */
static void
amd64bsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
amd64bsd_store_inferior_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -193,17 +191,3 @@ amd64bsd_store_inferior_registers (struct target_ops *ops,
perror_with_name (_("Couldn't write floating point status"));
}
}
/* Create a prototype *BSD/amd64 target. The client can override it
with local methods. */
struct target_ops *
amd64bsd_target (void)
{
struct target_ops *t;
t = x86bsd_target ();
t->to_fetch_registers = amd64bsd_fetch_inferior_registers;
t->to_store_registers = amd64bsd_store_inferior_registers;
return t;
}

44
gdb/amd64-bsd-nat.h Normal file
View File

@ -0,0 +1,44 @@
/* Native-dependent code for modern AMD64 BSD's.
Copyright (C) 2018 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 AMD64_BSD_NAT_H
#define AMD64_BSD_NAT_H
#include "x86-bsd-nat.h"
/* Helper functions. See definitions. */
extern void amd64bsd_fetch_inferior_registers (struct regcache *regcache,
int regnum);
extern void amd64bsd_store_inferior_registers (struct regcache *regcache,
int regnum);
/* A prototype *BSD/AMD64 target. */
template<typename BaseTarget>
class amd64_bsd_nat_target : public x86bsd_nat_target<BaseTarget>
{
public:
void fetch_registers (struct regcache *regcache, int regnum) override
{ amd64bsd_fetch_inferior_registers (regcache, regnum); }
void store_registers (struct regcache *regcache, int regnum) override
{ amd64bsd_store_inferior_registers (regcache, regnum); }
};
#endif /* i386-bsd-nat.h */

View File

@ -32,11 +32,25 @@
#include "fbsd-nat.h"
#include "amd64-tdep.h"
#include "amd64-nat.h"
#include "x86-bsd-nat.h"
#include "amd64-bsd-nat.h"
#include "x86-nat.h"
#include "x86-xstate.h"
class amd64_fbsd_nat_target final
: public amd64_bsd_nat_target<fbsd_nat_target>
{
public:
/* Add some extra features to the common *BSD/amd64 target. */
const struct target_desc *read_description () override;
#if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
int supports_stopped_by_hw_breakpoint () override;
#endif
};
static amd64_fbsd_nat_target the_amd64_fbsd_nat_target;
/* Offset in `struct reg' where MEMBER is stored. */
#define REG_OFFSET(member) offsetof (struct reg, member)
@ -141,10 +155,10 @@ amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
}
/* Implement the to_read_description method. */
/* Implement the read_description method. */
static const struct target_desc *
amd64fbsd_read_description (struct target_ops *ops)
const struct target_desc *
amd64_fbsd_nat_target::read_description ()
{
#ifdef PT_GETXSTATE_INFO
static int xsave_probed;
@ -185,20 +199,25 @@ amd64fbsd_read_description (struct target_ops *ops)
return i386_target_description (X86_XSTATE_SSE_MASK);
}
#if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
/* Implement the supports_stopped_by_hw_breakpoints method. */
int
amd64_fbsd_nat_target::supports_stopped_by_hw_breakpoint ()
{
return 1;
}
#endif
void
_initialize_amd64fbsd_nat (void)
{
struct target_ops *t;
int offset;
amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
/* Add some extra features to the common *BSD/i386 target. */
t = amd64bsd_target ();
t->to_read_description = amd64fbsd_read_description;
fbsd_nat_add_target (t);
add_target (&the_amd64_fbsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (amd64fbsd_supply_pcb);

View File

@ -30,7 +30,6 @@
#include "gdb_proc_service.h"
#include "amd64-nat.h"
#include "linux-nat.h"
#include "amd64-tdep.h"
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
@ -46,6 +45,15 @@
#define PTRACE_ARCH_PRCTL 30
#endif
struct amd64_linux_nat_target final : public x86_linux_nat_target
{
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static amd64_linux_nat_target the_amd64_linux_nat_target;
/* Mapping between the general-purpose registers in GNU/Linux x86-64
`struct user' format and GDB's register cache layout for GNU/Linux
i386.
@ -130,9 +138,8 @@ fill_fpregset (const struct regcache *regcache,
this for all registers (including the floating point and SSE
registers). */
static void
amd64_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
int tid;
@ -209,9 +216,8 @@ amd64_linux_fetch_inferior_registers (struct target_ops *ops,
-1, do this for all registers (including the floating-point and SSE
registers). */
static void
amd64_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
int tid;
@ -399,8 +405,6 @@ amd64_linux_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
void
_initialize_amd64_linux_nat (void)
{
struct target_ops *t;
amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
amd64_native_gregset64_reg_offset = amd64_linux_gregset_reg_offset;
@ -409,16 +413,11 @@ _initialize_amd64_linux_nat (void)
gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
== amd64_native_gregset32_num_regs);
/* Create a generic x86 GNU/Linux target. */
t = x86_linux_create_target ();
/* Add our register access methods. */
t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
t->to_store_registers = amd64_linux_store_inferior_registers;
linux_target = &the_amd64_linux_nat_target;
/* Add the target. */
x86_linux_add_target (t);
x86_linux_add_target (linux_target);
/* Add our siginfo layout converter. */
linux_nat_set_siginfo_fixup (t, amd64_linux_siginfo_fixup);
linux_nat_set_siginfo_fixup (linux_target, amd64_linux_siginfo_fixup);
}

View File

@ -49,9 +49,4 @@ extern void amd64_supply_native_gregset (struct regcache *regcache,
extern void amd64_collect_native_gregset (const struct regcache *regcache,
void *gregs, int regnum);
/* Create a prototype *BSD/amd64 target. The client can override it
with local methods. */
extern struct target_ops *amd64bsd_target (void);
#endif /* amd64-nat.h */

View File

@ -22,6 +22,7 @@
#include "nbsd-nat.h"
#include "amd64-tdep.h"
#include "amd64-bsd-nat.h"
#include "amd64-nat.h"
/* Mapping between the general-purpose registers in NetBSD/amd64
@ -53,17 +54,14 @@ static int amd64nbsd32_r_reg_offset[] =
15 * 8 /* %gs */
};
static amd64_bsd_nat_target<nbsd_nat_target> the_amd64_nbsd_nat_target;
void
_initialize_amd64nbsd_nat (void)
{
struct target_ops *t;
amd64_native_gregset32_reg_offset = amd64nbsd32_r_reg_offset;
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64nbsd32_r_reg_offset);
amd64_native_gregset64_reg_offset = amd64nbsd_r_reg_offset;
/* Add some extra features to the common *BSD/amd64 target. */
t = amd64bsd_target ();
t->to_pid_to_exec_file = nbsd_pid_to_exec_file;
add_target (t);
add_target (&the_amd64_nbsd_nat_target);
}

View File

@ -23,6 +23,7 @@
#include "target.h"
#include "amd64-tdep.h"
#include "amd64-bsd-nat.h"
#include "amd64-nat.h"
#include "obsd-nat.h"
@ -125,6 +126,8 @@ amd64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
static amd64_bsd_nat_target<obsd_nat_target> the_amd64_obsd_nat_target;
void
_initialize_amd64obsd_nat (void)
{
@ -132,8 +135,7 @@ _initialize_amd64obsd_nat (void)
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset);
amd64_native_gregset64_reg_offset = amd64obsd_r_reg_offset;
/* Add some extra features to the common *BSD/amd64 target. */
obsd_add_target (amd64bsd_target ());
add_target (&the_amd64_obsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (amd64obsd_supply_pcb);

View File

@ -29,6 +29,15 @@
#include "arm-fbsd-tdep.h"
#include "inf-ptrace.h"
struct arm_fbsd_nat_target : public fbsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
const struct target_desc *read_description () override;
};
static arm_fbsd_nat_target the_arm_fbsd_nat_target;
/* Determine if PT_GETREGS fetches REGNUM. */
static bool
@ -52,9 +61,8 @@ getvfpregs_supplies (struct gdbarch *gdbarch, int regnum)
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
arm_fbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
arm_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -87,9 +95,8 @@ arm_fbsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
static void
arm_fbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
arm_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -127,25 +134,19 @@ arm_fbsd_store_inferior_registers (struct target_ops *ops,
/* Implement the to_read_description method. */
static const struct target_desc *
arm_fbsd_read_description (struct target_ops *ops)
const struct target_desc *
arm_fbsd_nat_target::read_description ()
{
const struct target_desc *desc;
desc = arm_fbsd_read_description_auxv (ops);
desc = arm_fbsd_read_description_auxv (this);
if (desc == NULL)
desc = ops->beneath->to_read_description (ops->beneath);
desc = this->beneath->read_description ();
return desc;
}
void
_initialize_arm_fbsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = arm_fbsd_fetch_inferior_registers;
t->to_store_registers = arm_fbsd_store_inferior_registers;
t->to_read_description = arm_fbsd_read_description;
fbsd_nat_add_target (t);
add_target (&the_arm_fbsd_nat_target);
}

View File

@ -66,6 +66,38 @@
extern int arm_apcs_32;
class arm_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
/* Add our hardware breakpoint and watchpoint implementation. */
int can_use_hw_breakpoint (enum bptype, int, int) override;
int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
const struct target_desc *read_description () override;
};
static arm_linux_nat_target the_arm_linux_nat_target;
/* Get the whole floating point state of the process and store it
into regcache. */
@ -374,9 +406,8 @@ store_vfp_regs (const struct regcache *regcache)
regno == -1, otherwise fetch all general registers or all floating
point registers depending upon the value of regno. */
static void
arm_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
arm_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@ -412,9 +443,8 @@ arm_linux_fetch_inferior_registers (struct target_ops *ops,
regno == -1, otherwise store all general registers or all floating
point registers depending upon the value of regno. */
static void
arm_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
arm_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@ -495,8 +525,8 @@ ps_get_thread_area (struct ps_prochandle *ph,
return PS_OK;
}
static const struct target_desc *
arm_linux_read_description (struct target_ops *ops)
const struct target_desc *
arm_linux_nat_target::read_description ()
{
CORE_ADDR arm_hwcap = 0;
@ -516,9 +546,9 @@ arm_linux_read_description (struct target_ops *ops)
have_ptrace_getregset = TRIBOOL_TRUE;
}
if (target_auxv_search (ops, AT_HWCAP, &arm_hwcap) != 1)
if (target_auxv_search (this, AT_HWCAP, &arm_hwcap) != 1)
{
return ops->beneath->to_read_description (ops->beneath);
return this->beneath->read_description ();
}
if (arm_hwcap & HWCAP_IWMMXT)
@ -551,7 +581,7 @@ arm_linux_read_description (struct target_ops *ops)
return result;
}
return ops->beneath->to_read_description (ops->beneath);
return this->beneath->read_description ();
}
/* Information describing the hardware breakpoint capabilities. */
@ -635,10 +665,9 @@ arm_linux_get_hw_watchpoint_count (void)
/* Have we got a free break-/watch-point available for use? Returns -1 if
there is not an appropriate resource available, otherwise returns 1. */
static int
arm_linux_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type,
int cnt, int ot)
int
arm_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
int cnt, int ot)
{
if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
|| type == bp_access_watchpoint || type == bp_watchpoint)
@ -1026,10 +1055,9 @@ arm_linux_remove_hw_breakpoint1 (const struct arm_linux_hw_breakpoint *bpt,
}
/* Insert a Hardware breakpoint. */
static int
arm_linux_insert_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
arm_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct lwp_info *lp;
struct arm_linux_hw_breakpoint p;
@ -1045,10 +1073,9 @@ arm_linux_insert_hw_breakpoint (struct target_ops *self,
}
/* Remove a hardware breakpoint. */
static int
arm_linux_remove_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
arm_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct lwp_info *lp;
struct arm_linux_hw_breakpoint p;
@ -1065,9 +1092,8 @@ arm_linux_remove_hw_breakpoint (struct target_ops *self,
/* Are we able to use a hardware watchpoint for the LEN bytes starting at
ADDR? */
static int
arm_linux_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len)
int
arm_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
CORE_ADDR max_wp_length, aligned_addr;
@ -1098,11 +1124,10 @@ arm_linux_region_ok_for_hw_watchpoint (struct target_ops *self,
}
/* Insert a Hardware breakpoint. */
static int
arm_linux_insert_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type rw,
struct expression *cond)
int
arm_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type rw,
struct expression *cond)
{
struct lwp_info *lp;
struct arm_linux_hw_breakpoint p;
@ -1118,10 +1143,10 @@ arm_linux_insert_watchpoint (struct target_ops *self,
}
/* Remove a hardware breakpoint. */
static int
arm_linux_remove_watchpoint (struct target_ops *self, CORE_ADDR addr,
int len, enum target_hw_bp_type rw,
struct expression *cond)
int
arm_linux_nat_target::remove_watchpoint (CORE_ADDR addr,
int len, enum target_hw_bp_type rw,
struct expression *cond)
{
struct lwp_info *lp;
struct arm_linux_hw_breakpoint p;
@ -1137,8 +1162,8 @@ arm_linux_remove_watchpoint (struct target_ops *self, CORE_ADDR addr,
}
/* What was the data address the target was stopped on accessing. */
static int
arm_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
int
arm_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
{
siginfo_t siginfo;
int slot;
@ -1167,17 +1192,17 @@ arm_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
}
/* Has the target been stopped by hitting a watchpoint? */
static int
arm_linux_stopped_by_watchpoint (struct target_ops *ops)
int
arm_linux_nat_target::stopped_by_watchpoint ()
{
CORE_ADDR addr;
return arm_linux_stopped_data_address (ops, &addr);
return stopped_data_address (&addr);
}
static int
arm_linux_watchpoint_addr_within_range (struct target_ops *target,
CORE_ADDR addr,
CORE_ADDR start, int length)
int
arm_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
CORE_ADDR start,
int length)
{
return start <= addr && start + length - 1 >= addr;
}
@ -1294,30 +1319,11 @@ arm_linux_new_fork (struct lwp_info *parent, pid_t child_pid)
void
_initialize_arm_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Add our register access methods. */
t->to_fetch_registers = arm_linux_fetch_inferior_registers;
t->to_store_registers = arm_linux_store_inferior_registers;
/* Add our hardware breakpoint and watchpoint implementation. */
t->to_can_use_hw_breakpoint = arm_linux_can_use_hw_breakpoint;
t->to_insert_hw_breakpoint = arm_linux_insert_hw_breakpoint;
t->to_remove_hw_breakpoint = arm_linux_remove_hw_breakpoint;
t->to_region_ok_for_hw_watchpoint = arm_linux_region_ok_for_hw_watchpoint;
t->to_insert_watchpoint = arm_linux_insert_watchpoint;
t->to_remove_watchpoint = arm_linux_remove_watchpoint;
t->to_stopped_by_watchpoint = arm_linux_stopped_by_watchpoint;
t->to_stopped_data_address = arm_linux_stopped_data_address;
t->to_watchpoint_addr_within_range = arm_linux_watchpoint_addr_within_range;
t->to_read_description = arm_linux_read_description;
target_ops *t = &the_arm_linux_nat_target;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_arm_linux_nat_target;
add_target (t);
/* Handle thread creation and exit. */
linux_nat_set_new_thread (t, arm_linux_new_thread);

View File

@ -30,6 +30,16 @@
#include "arm-tdep.h"
#include "inf-ptrace.h"
class arm_netbsd_nat_target final : public inf_ptrace_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static arm_netbsd_nat_target the_arm_netbsd_nat_target;
extern int arm_apcs_32;
static void
@ -190,9 +200,8 @@ fetch_fp_regs (struct regcache *regcache)
arm_supply_fparegset (regcache, &inferior_fp_registers);
}
static void
armnbsd_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
arm_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
if (regno >= 0)
{
@ -391,9 +400,8 @@ store_fp_regs (const struct regcache *regcache)
warning (_("unable to store floating-point registers"));
}
static void
armnbsd_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
arm_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
{
if (regno >= 0)
{
@ -461,12 +469,7 @@ static struct core_fns arm_netbsd_elfcore_fns =
void
_initialize_arm_netbsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = armnbsd_fetch_registers;
t->to_store_registers = armnbsd_store_registers;
add_target (t);
add_target (&the_arm_netbsd_nat_target);
deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
}

View File

@ -283,16 +283,15 @@ default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
Return -1 if there is insufficient buffer for a whole entry.
Return 1 if an entry was read into *TYPEP and *VALP. */
int
target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
target_auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
{
struct gdbarch *gdbarch = target_gdbarch();
if (gdbarch_auxv_parse_p (gdbarch))
return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp);
return current_target.to_auxv_parse (&current_target, readptr, endptr,
typep, valp);
return target_stack->auxv_parse (readptr, endptr, typep, valp);
}
@ -382,7 +381,7 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
size_t len = info->data->size ();
while (1)
switch (target_auxv_parse (ops, &ptr, data + len, &type, &val))
switch (target_auxv_parse (&ptr, data + len, &type, &val))
{
case 1: /* Here's an entry, check it. */
if (type == match)
@ -532,7 +531,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
gdb_byte *ptr = data;
size_t len = info->data->size ();
while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
while (target_auxv_parse (&ptr, data + len, &type, &val) > 0)
{
gdbarch_print_auxv_entry (gdbarch, file, type, val);
++ents;
@ -550,7 +549,7 @@ info_auxv_command (const char *cmd, int from_tty)
error (_("The program has no auxiliary information now."));
else
{
int ents = fprint_target_auxv (gdb_stdout, &current_target);
int ents = fprint_target_auxv (gdb_stdout, target_stack);
if (ents < 0)
error (_("No auxiliary vector found, or failed reading it."));

View File

@ -35,8 +35,7 @@ extern int default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
Return 0 if *READPTR is already at the end of the buffer.
Return -1 if there is insufficient buffer for a whole entry.
Return 1 if an entry was read into *TYPEP and *VALP. */
extern int target_auxv_parse (struct target_ops *ops,
gdb_byte **readptr, gdb_byte *endptr,
extern int target_auxv_parse (gdb_byte **readptr, gdb_byte *endptr,
CORE_ADDR *typep, CORE_ADDR *valp);
/* Extract the auxiliary vector entry with a_type matching MATCH.

View File

@ -1555,7 +1555,7 @@ avr_io_reg_read_command (const char *args, int from_tty)
/* Find out how many io registers the target has. */
gdb::optional<gdb::byte_vector> buf
= target_read_alloc (&current_target, TARGET_OBJECT_AVR, "avr.io_reg");
= target_read_alloc (target_stack, TARGET_OBJECT_AVR, "avr.io_reg");
if (!buf)
{
@ -1589,7 +1589,7 @@ avr_io_reg_read_command (const char *args, int from_tty)
j = nreg - i; /* last block is less than 8 registers */
snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
buf = target_read_alloc (&current_target, TARGET_OBJECT_AVR, query);
buf = target_read_alloc (target_stack, TARGET_OBJECT_AVR, query);
if (!buf)
{

View File

@ -23,36 +23,58 @@
#include "exec.h"
#include "gdb_bfd.h"
/* The object that is stored in the target_ops->to_data field has this
type. */
struct target_bfd_data
/* A target that wraps a BFD. */
class target_bfd : public target_ops
{
public:
explicit target_bfd (struct bfd *bfd);
~target_bfd () override;
const char *shortname () override
{ return "bfd"; }
const char *longname () override
{ return _("BFD backed target"); }
const char *doc () override
{ return _("You should never see this"); }
void close () override;
target_xfer_status
xfer_partial (target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
target_section_table *get_section_table () override;
private:
/* The BFD we're wrapping. */
struct bfd *bfd;
struct bfd *m_bfd;
/* The section table build from the ALLOC sections in BFD. Note
that we can't rely on extracting the BFD from a random section in
the table, since the table can be legitimately empty. */
struct target_section_table table;
struct target_section_table m_table;
};
static enum target_xfer_status
target_bfd_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
target_xfer_status
target_bfd::xfer_partial (target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
{
struct target_bfd_data *data = (struct target_bfd_data *) ops->to_data;
return section_table_xfer_memory_partial (readbuf, writebuf,
offset, len, xfered_len,
data->table.sections,
data->table.sections_end,
m_table.sections,
m_table.sections_end,
NULL);
}
default:
@ -60,44 +82,36 @@ target_bfd_xfer_partial (struct target_ops *ops,
}
}
static struct target_section_table *
target_bfd_get_section_table (struct target_ops *ops)
target_section_table *
target_bfd::get_section_table ()
{
struct target_bfd_data *data = (struct target_bfd_data *) ops->to_data;
return &data->table;
return &m_table;
}
static void
target_bfd_close (struct target_ops *t)
target_bfd::target_bfd (struct bfd *abfd)
{
struct target_bfd_data *data = (struct target_bfd_data *) t->to_data;
gdb_bfd_unref (data->bfd);
xfree (data->table.sections);
xfree (data);
xfree (t);
this->to_stratum = file_stratum;
m_bfd = abfd;
gdb_bfd_ref (abfd);
m_table.sections = NULL;
m_table.sections_end = NULL;
build_section_table (abfd, &m_table.sections, &m_table.sections_end);
}
struct target_ops *
target_bfd::~target_bfd ()
{
gdb_bfd_unref (m_bfd);
xfree (m_table.sections);
}
target_ops *
target_bfd_reopen (struct bfd *abfd)
{
struct target_ops *t;
struct target_bfd_data *data;
data = XCNEW (struct target_bfd_data);
data->bfd = abfd;
gdb_bfd_ref (abfd);
build_section_table (abfd, &data->table.sections, &data->table.sections_end);
t = XCNEW (struct target_ops);
t->to_shortname = "bfd";
t->to_longname = _("BFD backed target");
t->to_doc = _("You should never see this");
t->to_get_section_table = target_bfd_get_section_table;
t->to_xfer_partial = target_bfd_xfer_partial;
t->to_close = target_bfd_close;
t->to_data = data;
t->to_magic = OPS_MAGIC;
return t;
return new target_bfd (abfd);
}
void
target_bfd::close ()
{
delete this;
}

View File

@ -3493,8 +3493,7 @@ create_exception_master_breakpoint (void)
}
addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
&current_target);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, target_stack);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
&internal_breakpoint_ops);
initialize_explicit_location (&explicit_loc);
@ -4753,7 +4752,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
return 0;
}
if (!target_stopped_data_address (&current_target, &addr))
if (!target_stopped_data_address (target_stack, &addr))
{
/* We were stopped by a watchpoint, but we don't know where.
Mark all watchpoints as unknown. */
@ -4793,7 +4792,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
}
}
/* Exact match not required. Within range is sufficient. */
else if (target_watchpoint_addr_within_range (&current_target,
else if (target_watchpoint_addr_within_range (target_stack,
addr, loc->address,
loc->length))
{

View File

@ -56,16 +56,56 @@ static struct pcb *bsd_kvm_paddr;
register state from PCB and supplies it to REGCACHE. */
static int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb);
/* Target ops for libkvm interface. */
static struct target_ops bsd_kvm_ops;
/* This is the ptid we use while we're connected to kvm. The kvm
target currently doesn't export any view of the running processes,
so this represents the kernel task. */
static ptid_t bsd_kvm_ptid;
/* The libkvm target. */
class bsd_kvm_target final : public target_ops
{
public:
bsd_kvm_target ()
{ this->to_stratum = process_stratum; }
const char *shortname () override
{ return "kvm"; }
const char *longname () override
{ return _("Kernel memory interface"); }
const char *doc () override
{
return _("Use a kernel virtual memory image as a target.\n\
Optionally specify the filename of a core dump.");
}
void open (const char *, int) override;
void close () override;
void fetch_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void files_info () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
int has_memory () override { return 1; }
int has_stack () override { return 1; }
int has_registers () override { return 1; }
};
/* Target ops for libkvm interface. */
static bsd_kvm_target bsd_kvm_ops;
static void
bsd_kvm_open (const char *arg, int from_tty)
bsd_kvm_target::open (const char *arg, int from_tty)
{
char errbuf[_POSIX2_LINE_MAX];
char *execfile = NULL;
@ -107,8 +147,8 @@ bsd_kvm_open (const char *arg, int from_tty)
print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
}
static void
bsd_kvm_close (struct target_ops *self)
void
bsd_kvm_target::close ()
{
if (core_kd)
{
@ -134,11 +174,11 @@ bsd_kvm_xfer_memory (CORE_ADDR addr, ULONGEST len,
return nbytes;
}
static enum target_xfer_status
bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
bsd_kvm_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
@ -162,8 +202,8 @@ bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
}
}
static void
bsd_kvm_files_info (struct target_ops *ops)
void
bsd_kvm_target::files_info ()
{
if (bsd_kvm_corefile && strcmp (bsd_kvm_corefile, _PATH_MEM) != 0)
printf_filtered (_("\tUsing the kernel crash dump %s.\n"),
@ -186,9 +226,8 @@ bsd_kvm_fetch_pcb (struct regcache *regcache, struct pcb *paddr)
return bsd_kvm_supply_pcb (regcache, &pcb);
}
static void
bsd_kvm_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
bsd_kvm_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct nlist nl[2];
@ -325,27 +364,20 @@ bsd_kvm_pcb_cmd (const char *arg, int fromtty)
print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
}
static int
bsd_kvm_thread_alive (struct target_ops *ops,
ptid_t ptid)
int
bsd_kvm_target::thread_alive (ptid_t ptid)
{
return 1;
}
static const char *
bsd_kvm_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
bsd_kvm_target::pid_to_str (ptid_t ptid)
{
static char buf[64];
xsnprintf (buf, sizeof buf, "<kvm>");
return buf;
}
static int
bsd_kvm_return_one (struct target_ops *ops)
{
return 1;
}
/* Add the libkvm interface to the list of all possible targets and
register CUPPLY_PCB as the architecture-specific process control
block interpreter. */
@ -356,23 +388,6 @@ bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
gdb_assert (bsd_kvm_supply_pcb == NULL);
bsd_kvm_supply_pcb = supply_pcb;
bsd_kvm_ops.to_shortname = "kvm";
bsd_kvm_ops.to_longname = _("Kernel memory interface");
bsd_kvm_ops.to_doc = _("Use a kernel virtual memory image as a target.\n\
Optionally specify the filename of a core dump.");
bsd_kvm_ops.to_open = bsd_kvm_open;
bsd_kvm_ops.to_close = bsd_kvm_close;
bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers;
bsd_kvm_ops.to_xfer_partial = bsd_kvm_xfer_partial;
bsd_kvm_ops.to_files_info = bsd_kvm_files_info;
bsd_kvm_ops.to_thread_alive = bsd_kvm_thread_alive;
bsd_kvm_ops.to_pid_to_str = bsd_kvm_pid_to_str;
bsd_kvm_ops.to_stratum = process_stratum;
bsd_kvm_ops.to_has_memory = bsd_kvm_return_one;
bsd_kvm_ops.to_has_stack = bsd_kvm_return_one;
bsd_kvm_ops.to_has_registers = bsd_kvm_return_one;
bsd_kvm_ops.to_magic = OPS_MAGIC;
add_target (&bsd_kvm_ops);
add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\

View File

@ -33,8 +33,40 @@
#include "bsd-uthread.h"
/* HACK: Save the bsd_uthreads ops returned by bsd_uthread_target. */
static struct target_ops *bsd_uthread_ops_hack;
struct bsd_uthread_target final : public target_ops
{
bsd_uthread_target ()
{ to_stratum = thread_stratum; }
const char *shortname () override
{ return "bsd-uthreads"; }
const char *longname () override
{ return _("BSD user-level threads"); }
const char *doc () override
{ return _("BSD user-level threads"); }
void close () override;
void mourn_inferior () override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
int thread_alive (ptid_t ptid) override;
void update_thread_list () override;
const char *extra_thread_info (struct thread_info *) override;
const char *pid_to_str (ptid_t) override;
};
static bsd_uthread_target bsd_uthread_ops;
/* Architecture-specific operations. */
@ -200,15 +232,15 @@ bsd_uthread_activate (struct objfile *objfile)
bsd_uthread_thread_ctx_offset =
bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
push_target (bsd_uthread_ops_hack);
push_target (&bsd_uthread_ops);
bsd_uthread_active = 1;
return 1;
}
/* Cleanup due to deactivation. */
static void
bsd_uthread_close (struct target_ops *self)
void
bsd_uthread_target::close ()
{
bsd_uthread_active = 0;
bsd_uthread_thread_run_addr = 0;
@ -228,7 +260,7 @@ bsd_uthread_deactivate (void)
if (!bsd_uthread_active)
return;
unpush_target (bsd_uthread_ops_hack);
unpush_target (&bsd_uthread_ops);
}
static void
@ -275,24 +307,23 @@ bsd_uthread_solib_unloaded (struct so_list *so)
bsd_uthread_deactivate ();
}
static void
bsd_uthread_mourn_inferior (struct target_ops *ops)
void
bsd_uthread_target::mourn_inferior ()
{
struct target_ops *beneath = find_target_beneath (ops);
beneath->to_mourn_inferior (beneath);
struct target_ops *beneath = find_target_beneath (this);
beneath->mourn_inferior ();
bsd_uthread_deactivate ();
}
static void
bsd_uthread_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
bsd_uthread_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
struct bsd_uthread_ops *uthread_ops
= (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
ptid_t ptid = regcache_get_ptid (regcache);
CORE_ADDR addr = ptid_get_tid (ptid);
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
CORE_ADDR active_addr;
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
@ -301,7 +332,7 @@ bsd_uthread_fetch_registers (struct target_ops *ops,
inferior_ptid = ptid;
/* Always fetch the appropriate registers from the layer beneath. */
beneath->to_fetch_registers (beneath, regcache, regnum);
beneath->fetch_registers (regcache, regnum);
/* FIXME: That might have gotten us more than we asked for. Make
sure we overwrite all relevant registers with values from the
@ -317,14 +348,13 @@ bsd_uthread_fetch_registers (struct target_ops *ops,
}
}
static void
bsd_uthread_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
bsd_uthread_target::store_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
struct bsd_uthread_ops *uthread_ops
= (struct bsd_uthread_ops *) gdbarch_data (gdbarch, bsd_uthread_data);
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
ptid_t ptid = regcache_get_ptid (regcache);
CORE_ADDR addr = ptid_get_tid (ptid);
CORE_ADDR active_addr;
@ -345,20 +375,20 @@ bsd_uthread_store_registers (struct target_ops *ops,
{
/* Updating the thread that is currently running; pass the
request to the layer beneath. */
beneath->to_store_registers (beneath, regcache, regnum);
beneath->store_registers (regcache, regnum);
}
}
static ptid_t
bsd_uthread_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
bsd_uthread_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
CORE_ADDR addr;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
/* Pass the request to the layer beneath. */
ptid = beneath->to_wait (beneath, ptid, status, options);
ptid = beneath->wait (ptid, status, options);
/* If the process is no longer alive, there's no point in figuring
out the thread ID. It will fail anyway. */
@ -399,20 +429,19 @@ bsd_uthread_wait (struct target_ops *ops,
return ptid;
}
static void
bsd_uthread_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal sig)
void
bsd_uthread_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
{
/* Pass the request to the layer beneath. */
struct target_ops *beneath = find_target_beneath (ops);
beneath->to_resume (beneath, ptid, step, sig);
struct target_ops *beneath = find_target_beneath (this);
beneath->resume (ptid, step, sig);
}
static int
bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
int
bsd_uthread_target::thread_alive (ptid_t ptid)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
CORE_ADDR addr = ptid_get_tid (ptid);
if (addr != 0)
@ -427,11 +456,11 @@ bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
return 0;
}
return beneath->to_thread_alive (beneath, ptid);
return beneath->thread_alive (ptid);
}
static void
bsd_uthread_update_thread_list (struct target_ops *ops)
void
bsd_uthread_target::update_thread_list ()
{
pid_t pid = ptid_get_pid (inferior_ptid);
int offset = bsd_uthread_thread_next_offset;
@ -487,9 +516,8 @@ static const char *bsd_uthread_state[] =
/* Return a string describing th state of the thread specified by
INFO. */
static const char *
bsd_uthread_extra_thread_info (struct target_ops *self,
struct thread_info *info)
const char *
bsd_uthread_target::extra_thread_info (thread_info *info)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
CORE_ADDR addr = ptid_get_tid (info->ptid);
@ -507,8 +535,8 @@ bsd_uthread_extra_thread_info (struct target_ops *self,
return NULL;
}
static const char *
bsd_uthread_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
bsd_uthread_target::pid_to_str (ptid_t ptid)
{
if (ptid_get_tid (ptid) != 0)
{
@ -522,36 +550,9 @@ bsd_uthread_pid_to_str (struct target_ops *ops, ptid_t ptid)
return normal_pid_to_str (ptid);
}
static struct target_ops *
bsd_uthread_target (void)
{
struct target_ops *t = XCNEW (struct target_ops);
t->to_shortname = "bsd-uthreads";
t->to_longname = "BSD user-level threads";
t->to_doc = "BSD user-level threads";
t->to_close = bsd_uthread_close;
t->to_mourn_inferior = bsd_uthread_mourn_inferior;
t->to_fetch_registers = bsd_uthread_fetch_registers;
t->to_store_registers = bsd_uthread_store_registers;
t->to_wait = bsd_uthread_wait;
t->to_resume = bsd_uthread_resume;
t->to_thread_alive = bsd_uthread_thread_alive;
t->to_update_thread_list = bsd_uthread_update_thread_list;
t->to_extra_thread_info = bsd_uthread_extra_thread_info;
t->to_pid_to_str = bsd_uthread_pid_to_str;
t->to_stratum = thread_stratum;
t->to_magic = OPS_MAGIC;
bsd_uthread_ops_hack = t;
return t;
}
void
_initialize_bsd_uthread (void)
{
complete_target_initialization (bsd_uthread_target ());
bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
gdb::observers::inferior_created.attach (bsd_uthread_inferior_created);

View File

@ -53,9 +53,6 @@ static int exec_file_hook_count = 0; /* Size of array. */
bfd *core_bfd = NULL;
/* corelow.c target. It is never NULL after GDB initialization. */
struct target_ops *core_target;
/* Backward compatability with old way of specifying core files. */
@ -65,12 +62,12 @@ core_file_command (const char *filename, int from_tty)
{
dont_repeat (); /* Either way, seems bogus. */
gdb_assert (core_target != NULL);
gdb_assert (the_core_target != NULL);
if (!filename)
(core_target->to_detach) (core_target, current_inferior (), from_tty);
the_core_target->detach (current_inferior (), from_tty);
else
(core_target->to_open) (filename, from_tty);
the_core_target->open (filename, from_tty);
}
@ -237,8 +234,7 @@ read_memory_object (enum target_object object, CORE_ADDR memaddr,
enum target_xfer_status status;
ULONGEST xfered_len;
status = target_xfer_partial (current_target.beneath,
object, NULL,
status = target_xfer_partial (target_stack, object, NULL,
myaddr + xfered, NULL,
memaddr + xfered, len - xfered,
&xfered_len);

View File

@ -50,6 +50,55 @@
#define O_LARGEFILE 0
#endif
/* The core file target. */
class core_target final : public target_ops
{
public:
core_target ()
{ to_stratum = process_stratum; }
const char *shortname () override
{ return "core"; }
const char *longname () override
{ return _("Local core dump file"); }
const char *doc () override
{
return _("\
Use a core file as a target. Specify the filename of the core file.");
}
void open (const char *, int) override;
void close () override;
void detach (inferior *, int) override;
void fetch_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void files_info () override;
int thread_alive (ptid_t ptid) override;
const struct target_desc *read_description () override;
const char *pid_to_str (ptid_t) override;
const char *thread_name (struct thread_info *) override;
int has_memory () override;
int has_stack () override;
int has_registers () override;
bool info_proc (const char *, enum info_proc_what) override;
};
/* See gdbcore.h. */
struct target_ops *the_core_target;
/* List of all available core_fns. On gdb startup, each core file
register reader calls deprecated_add_core_fns() to register
information on each core format it is prepared to read. */
@ -74,21 +123,15 @@ static struct gdbarch *core_gdbarch = NULL;
unix child targets. */
static struct target_section_table *core_data;
static void core_files_info (struct target_ops *);
static struct core_fns *sniff_core_bfd (bfd *);
static int gdb_check_format (bfd *);
static void core_close (struct target_ops *self);
static void core_close_cleanup (void *ignore);
static void add_to_thread_list (bfd *, asection *, void *);
static void init_core_ops (void);
static struct target_ops core_ops;
static core_target core_ops;
/* An arbitrary identifier for the core inferior. */
#define CORELOW_PID 1
@ -185,7 +228,7 @@ gdb_check_format (bfd *abfd)
stack spaces as empty. */
static void
core_close (struct target_ops *self)
core_close ()
{
if (core_bfd)
{
@ -216,7 +259,13 @@ core_close (struct target_ops *self)
static void
core_close_cleanup (void *ignore)
{
core_close (NULL);
core_close ();
}
void
core_target::close ()
{
core_close ();
}
/* Look for sections whose names start with `.reg/' so that we can
@ -266,8 +315,8 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
/* This routine opens and sets up the core file bfd. */
static void
core_open (const char *arg, int from_tty)
void
core_target::open (const char *arg, int from_tty)
{
const char *p;
int siggy;
@ -463,10 +512,10 @@ core_open (const char *arg, int from_tty)
}
}
static void
core_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
core_target::detach (inferior *inf, int from_tty)
{
unpush_target (ops);
unpush_target (this);
reinit_frame_cache ();
if (from_tty)
printf_filtered (_("No core file now.\n"));
@ -585,9 +634,8 @@ get_core_registers_cb (const char *sect_name, int size,
/* We just get all the registers, so we don't use regno. */
static void
get_core_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
core_target::fetch_registers (struct regcache *regcache, int regno)
{
int i;
struct gdbarch *gdbarch;
@ -619,8 +667,8 @@ get_core_registers (struct target_ops *ops,
regcache_raw_supply (regcache, i, NULL);
}
static void
core_files_info (struct target_ops *t)
void
core_target::files_info ()
{
print_section_info (core_data, core_bfd);
}
@ -655,11 +703,10 @@ add_to_spuid_list (bfd *abfd, asection *asect, void *list_p)
list->pos += 4;
}
static enum target_xfer_status
core_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
core_target::xfer_partial (enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
@ -861,35 +908,13 @@ core_xfer_partial (struct target_ops *ops, enum target_object object,
return TARGET_XFER_E_IO;
default:
return ops->beneath->to_xfer_partial (ops->beneath, object,
annex, readbuf,
writebuf, offset, len,
xfered_len);
return this->beneath->xfer_partial (object, annex, readbuf,
writebuf, offset, len,
xfered_len);
}
}
/* If mourn is being called in all the right places, this could be say
`gdb internal error' (since generic_mourn calls
breakpoint_init_inferior). */
static int
ignore (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return 0;
}
/* Implement the to_remove_breakpoint method. */
static int
core_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
{
return 0;
}
/* Okay, let's be honest: threads gleaned from a core file aren't
exactly lively, are they? On the other hand, if we don't claim
@ -897,8 +922,8 @@ core_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
to appear in an "info thread" command, which is quite a useful
behaviour.
*/
static int
core_thread_alive (struct target_ops *ops, ptid_t ptid)
int
core_target::thread_alive (ptid_t ptid)
{
return 1;
}
@ -908,24 +933,23 @@ core_thread_alive (struct target_ops *ops, ptid_t ptid)
wrapper could be avoided if targets got a chance to specialize
core_ops. */
static const struct target_desc *
core_read_description (struct target_ops *target)
const struct target_desc *
core_target::read_description ()
{
if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch))
{
const struct target_desc *result;
result = gdbarch_core_read_description (core_gdbarch,
target, core_bfd);
result = gdbarch_core_read_description (core_gdbarch, this, core_bfd);
if (result != NULL)
return result;
}
return target->beneath->to_read_description (target->beneath);
return this->beneath->read_description ();
}
static const char *
core_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
core_target::pid_to_str (ptid_t ptid)
{
static char buf[64];
struct inferior *inf;
@ -956,8 +980,8 @@ core_pid_to_str (struct target_ops *ops, ptid_t ptid)
return buf;
}
static const char *
core_thread_name (struct target_ops *self, struct thread_info *thr)
const char *
core_target::thread_name (struct thread_info *thr)
{
if (core_gdbarch
&& gdbarch_core_thread_name_p (core_gdbarch))
@ -965,29 +989,28 @@ core_thread_name (struct target_ops *self, struct thread_info *thr)
return NULL;
}
static int
core_has_memory (struct target_ops *ops)
int
core_target::has_memory ()
{
return (core_bfd != NULL);
}
static int
core_has_stack (struct target_ops *ops)
int
core_target::has_stack ()
{
return (core_bfd != NULL);
}
static int
core_has_registers (struct target_ops *ops)
int
core_target::has_registers ()
{
return (core_bfd != NULL);
}
/* Implement the to_info_proc method. */
static void
core_info_proc (struct target_ops *ops, const char *args,
enum info_proc_what request)
bool
core_target::info_proc (const char *args, enum info_proc_what request)
{
struct gdbarch *gdbarch = get_current_arch ();
@ -995,47 +1018,18 @@ core_info_proc (struct target_ops *ops, const char *args,
method on gdbarch, not 'info_proc'. */
if (gdbarch_core_info_proc_p (gdbarch))
gdbarch_core_info_proc (gdbarch, args, request);
}
/* Fill in core_ops with its defined operations and properties. */
static void
init_core_ops (void)
{
core_ops.to_shortname = "core";
core_ops.to_longname = "Local core dump file";
core_ops.to_doc =
"Use a core file as a target. Specify the filename of the core file.";
core_ops.to_open = core_open;
core_ops.to_close = core_close;
core_ops.to_detach = core_detach;
core_ops.to_fetch_registers = get_core_registers;
core_ops.to_xfer_partial = core_xfer_partial;
core_ops.to_files_info = core_files_info;
core_ops.to_insert_breakpoint = ignore;
core_ops.to_remove_breakpoint = core_remove_breakpoint;
core_ops.to_thread_alive = core_thread_alive;
core_ops.to_read_description = core_read_description;
core_ops.to_pid_to_str = core_pid_to_str;
core_ops.to_thread_name = core_thread_name;
core_ops.to_stratum = process_stratum;
core_ops.to_has_memory = core_has_memory;
core_ops.to_has_stack = core_has_stack;
core_ops.to_has_registers = core_has_registers;
core_ops.to_info_proc = core_info_proc;
core_ops.to_magic = OPS_MAGIC;
if (core_target)
internal_error (__FILE__, __LINE__,
_("init_core_ops: core target already exists (\"%s\")."),
core_target->to_longname);
core_target = &core_ops;
return true;
}
void
_initialize_corelow (void)
{
init_core_ops ();
if (the_core_target != NULL)
internal_error (__FILE__, __LINE__,
_("core target already exists (\"%s\")."),
the_core_target->longname ());
the_core_target = &core_ops;
add_target_with_completer (&core_ops, filename_completer);
}

103
gdb/ctf.c
View File

@ -32,6 +32,40 @@
#include <ctype.h>
#include <algorithm>
/* The CTF target. */
class ctf_target final : public tracefile_target
{
public:
const char *shortname () override
{ return "ctf"; }
const char *longname () override
{ return _("CTF file"); }
const char *doc () override
{
return _("\
Use a CTF directory as a target.\n\
Specify the filename of the CTF directory.");
}
void open (const char *, int) override;
void close () override;
void fetch_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void files_info () override;
int trace_find (enum trace_find_type type, int num,
CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) override;
int get_trace_state_variable_value (int tsv, LONGEST *val) override;
traceframe_info_up traceframe_info () override;
};
/* GDB saves trace buffers and other information (such as trace
status) got from the remote target into Common Trace Format (CTF).
The following types of information are expected to save in CTF:
@ -826,7 +860,7 @@ static struct bt_iter_pos *start_pos;
/* The name of CTF directory. */
static char *trace_dirname;
static struct target_ops ctf_ops;
static ctf_target ctf_ops;
/* Destroy ctf iterator and context. */
@ -1074,8 +1108,8 @@ ctf_read_tp (struct uploaded_tp **uploaded_tps)
definitions from the first packet. Set the start position at the
second packet which contains events on trace blocks. */
static void
ctf_open (const char *dirname, int from_tty)
void
ctf_target::open (const char *dirname, int from_tty)
{
struct bt_ctf_event *event;
uint32_t event_id;
@ -1142,8 +1176,8 @@ ctf_open (const char *dirname, int from_tty)
/* This is the implementation of target_ops method to_close. Destroy
CTF iterator and context. */
static void
ctf_close (struct target_ops *self)
void
ctf_target::close ()
{
int pid;
@ -1161,8 +1195,8 @@ ctf_close (struct target_ops *self)
/* This is the implementation of target_ops method to_files_info.
Print the directory name of CTF trace data. */
static void
ctf_files_info (struct target_ops *t)
void
ctf_target::files_info ()
{
printf_filtered ("\t`%s'\n", trace_dirname);
}
@ -1172,9 +1206,8 @@ ctf_files_info (struct target_ops *t)
extract contents from events, and set REGCACHE with the contents.
If no matched events are found, mark registers unavailable. */
static void
ctf_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
ctf_target::fetch_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
struct bt_ctf_event *event = NULL;
@ -1258,11 +1291,11 @@ ctf_fetch_registers (struct target_ops *ops,
OFFSET is within the range, read the contents from events to
READBUF. */
static enum target_xfer_status
ctf_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
ctf_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
/* We're only doing regular memory for now. */
if (object != TARGET_OBJECT_MEMORY)
@ -1397,9 +1430,8 @@ ctf_xfer_partial (struct target_ops *ops, enum target_object object,
trace variable is found, set the value of it to *VAL and return
true, otherwise return false. */
static int
ctf_get_trace_state_variable_value (struct target_ops *self,
int tsvnum, LONGEST *val)
int
ctf_target::get_trace_state_variable_value (int tsvnum, LONGEST *val)
{
struct bt_iter_pos *pos;
int found = 0;
@ -1515,9 +1547,9 @@ ctf_get_traceframe_address (void)
Iterate the events whose name is "frame", extract the tracepoint
number in it. Return traceframe number when matched. */
static int
ctf_trace_find (struct target_ops *self, enum trace_find_type type, int num,
CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
int
ctf_target::trace_find (enum trace_find_type type, int num,
CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
{
int tfnum = 0;
int found = 0;
@ -1617,10 +1649,10 @@ ctf_trace_find (struct target_ops *self, enum trace_find_type type, int num,
frame, extract memory range information, and return them in
traceframe_info. */
static traceframe_info_up
ctf_traceframe_info (struct target_ops *self)
traceframe_info_up
ctf_target::traceframe_info ()
{
traceframe_info_up info (new traceframe_info);
traceframe_info_up info (new struct traceframe_info);
const char *name;
struct bt_iter_pos *pos;
@ -1684,27 +1716,6 @@ ctf_traceframe_info (struct target_ops *self)
return info;
}
static void
init_ctf_ops (void)
{
memset (&ctf_ops, 0, sizeof (ctf_ops));
init_tracefile_ops (&ctf_ops);
ctf_ops.to_shortname = "ctf";
ctf_ops.to_longname = "CTF file";
ctf_ops.to_doc = "Use a CTF directory as a target.\n\
Specify the filename of the CTF directory.";
ctf_ops.to_open = ctf_open;
ctf_ops.to_close = ctf_close;
ctf_ops.to_fetch_registers = ctf_fetch_registers;
ctf_ops.to_xfer_partial = ctf_xfer_partial;
ctf_ops.to_files_info = ctf_files_info;
ctf_ops.to_trace_find = ctf_trace_find;
ctf_ops.to_get_trace_state_variable_value
= ctf_get_trace_state_variable_value;
ctf_ops.to_traceframe_info = ctf_traceframe_info;
}
#endif
/* module initialization */
@ -1713,8 +1724,6 @@ void
_initialize_ctf (void)
{
#if HAVE_LIBBABELTRACE
init_ctf_ops ();
add_target_with_completer (&ctf_ops, filename_completer);
#endif
}

View File

@ -83,36 +83,12 @@
#define PTRACE(CMD, PID, ADDR, SIG) \
darwin_ptrace(#CMD, CMD, (PID), (ADDR), (SIG))
static void darwin_interrupt (struct target_ops *self);
static void darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal signal);
static void darwin_resume (ptid_t ptid, int step,
enum gdb_signal signal);
static ptid_t darwin_wait_to (struct target_ops *ops, ptid_t ptid,
struct target_waitstatus *status, int options);
static ptid_t darwin_wait (ptid_t ptid, struct target_waitstatus *status);
static void darwin_mourn_inferior (struct target_ops *ops);
static void darwin_kill_inferior (struct target_ops *ops);
static void darwin_ptrace_me (void);
static void darwin_ptrace_him (int pid);
static void darwin_create_inferior (struct target_ops *ops,
const char *exec_file,
const std::string &allargs,
char **env, int from_tty);
static void darwin_files_info (struct target_ops *ops);
static const char *darwin_pid_to_str (struct target_ops *ops, ptid_t tpid);
static int darwin_thread_alive (struct target_ops *ops, ptid_t tpid);
static void darwin_encode_reply (mig_reply_error_t *reply,
mach_msg_header_t *hdr, integer_t code);
@ -942,8 +918,8 @@ darwin_suspend_inferior_threads (struct inferior *inf)
}
}
static void
darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
void
darwin_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
{
struct target_waitstatus status;
int pid;
@ -1007,13 +983,6 @@ darwin_resume (ptid_t ptid, int step, enum gdb_signal signal)
}
}
static void
darwin_resume_to (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal signal)
{
return darwin_resume (ptid, step, signal);
}
static ptid_t
darwin_decode_message (mach_msg_header_t *hdr,
darwin_thread_t **pthread,
@ -1334,22 +1303,22 @@ darwin_wait (ptid_t ptid, struct target_waitstatus *status)
return res;
}
static ptid_t
darwin_wait_to (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
darwin_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
return darwin_wait (ptid, status);
}
static void
darwin_interrupt (struct target_ops *self)
void
darwin_nat_target::interrupt ()
{
struct inferior *inf = current_inferior ();
darwin_inferior *priv = get_darwin_inferior (inf);
/* FIXME: handle in no_ptrace mode. */
gdb_assert (!priv->no_ptrace);
kill (inf->pid, SIGINT);
::kill (inf->pid, SIGINT);
}
/* Deallocate threads port and vector. */
@ -1368,8 +1337,8 @@ darwin_deallocate_threads (struct inferior *inf)
priv->threads.clear ();
}
static void
darwin_mourn_inferior (struct target_ops *ops)
void
darwin_nat_target::mourn_inferior ()
{
struct inferior *inf = current_inferior ();
darwin_inferior *priv = get_darwin_inferior (inf);
@ -1414,7 +1383,7 @@ darwin_mourn_inferior (struct target_ops *ops)
inf->priv = NULL;
inf_child_mourn_inferior (ops);
inf_child_target::mourn_inferior ();
}
static void
@ -1538,8 +1507,8 @@ darwin_setup_exceptions (struct inferior *inf)
kret);
}
static void
darwin_kill_inferior (struct target_ops *ops)
void
darwin_nat_target::kill ()
{
struct inferior *inf = current_inferior ();
darwin_inferior *priv = get_darwin_inferior (inf);
@ -1559,7 +1528,7 @@ darwin_kill_inferior (struct target_ops *ops)
darwin_reply_to_all_pending_messages (inf);
res = kill (inf->pid, 9);
res = ::kill (inf->pid, 9);
if (res == 0)
{
@ -1835,11 +1804,10 @@ darwin_execvp (const char *file, char * const argv[], char * const env[])
posix_spawnp (NULL, argv[0], NULL, &attr, argv, env);
}
static void
darwin_create_inferior (struct target_ops *ops,
const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
void
darwin_nat_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
/* Do the hard work. */
fork_inferior (exec_file, allargs, env, darwin_ptrace_me,
@ -1877,8 +1845,8 @@ darwin_setup_fake_stop_event (struct inferior *inf)
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
static void
darwin_attach (struct target_ops *ops, const char *args, int from_tty)
void
darwin_nat_target::attach (const char *args, int from_tty)
{
pid_t pid;
pid_t pid2;
@ -1906,7 +1874,7 @@ darwin_attach (struct target_ops *ops, const char *args, int from_tty)
gdb_flush (gdb_stdout);
}
if (pid == 0 || kill (pid, 0) < 0)
if (pid == 0 || ::kill (pid, 0) < 0)
error (_("Can't attach to process %d: %s (%d)"),
pid, safe_strerror (errno), errno);
@ -1937,8 +1905,9 @@ darwin_attach (struct target_ops *ops, const char *args, int from_tty)
to work, it may be necessary for the process to have been
previously attached. It *might* work if the program was
started via fork. */
static void
darwin_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
darwin_nat_target::detach (inferior *inf, int from_tty)
{
pid_t pid = ptid_get_pid (inferior_ptid);
darwin_inferior *priv = get_darwin_inferior (inf);
@ -1971,16 +1940,11 @@ darwin_detach (struct target_ops *ops, inferior *inf, int from_tty)
if (priv->no_ptrace)
darwin_resume_inferior (inf);
darwin_mourn_inferior (ops);
mourn_inferior ();
}
static void
darwin_files_info (struct target_ops *ops)
{
}
static const char *
darwin_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
darwin_nat_target::pid_to_str (ptid_t ptid)
{
static char buf[80];
long tid = ptid_get_tid (ptid);
@ -1995,8 +1959,8 @@ darwin_pid_to_str (struct target_ops *ops, ptid_t ptid)
return normal_pid_to_str (ptid);
}
static int
darwin_thread_alive (struct target_ops *ops, ptid_t ptid)
int
darwin_nat_target::thread_alive (ptid_t ptid)
{
return 1;
}
@ -2193,11 +2157,11 @@ darwin_read_dyld_info (task_t task, CORE_ADDR addr, gdb_byte *rdaddr,
static enum target_xfer_status
darwin_xfer_partial (struct target_ops *ops,
enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
darwin_nat_target::xfer_partial (enum target_object object, const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
struct inferior *inf = current_inferior ();
darwin_inferior *priv = get_darwin_inferior (inf);
@ -2264,8 +2228,8 @@ set_enable_mach_exceptions (const char *args, int from_tty,
}
}
static char *
darwin_pid_to_exec_file (struct target_ops *self, int pid)
char *
darwin_nat_target::pid_to_exec_file (int pid)
{
static char path[PATH_MAX];
int res;
@ -2277,8 +2241,8 @@ darwin_pid_to_exec_file (struct target_ops *self, int pid)
return NULL;
}
static ptid_t
darwin_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
ptid_t
darwin_nat_target::get_ada_task_ptid (long lwp, long thread)
{
struct inferior *inf = current_inferior ();
darwin_inferior *priv = get_darwin_inferior (inf);
@ -2342,14 +2306,14 @@ darwin_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
return null_ptid;
}
static int
darwin_supports_multi_process (struct target_ops *self)
int
darwin_nat_target::supports_multi_process ()
{
return 1;
}
void
_initialize_darwin_inferior (void)
_initialize_darwin_nat ()
{
kern_return_t kret;
@ -2364,30 +2328,6 @@ _initialize_darwin_inferior (void)
MACH_CHECK_ERROR (kret);
}
darwin_ops = inf_child_target ();
darwin_ops->to_create_inferior = darwin_create_inferior;
darwin_ops->to_attach = darwin_attach;
darwin_ops->to_attach_no_wait = 0;
darwin_ops->to_detach = darwin_detach;
darwin_ops->to_files_info = darwin_files_info;
darwin_ops->to_wait = darwin_wait_to;
darwin_ops->to_mourn_inferior = darwin_mourn_inferior;
darwin_ops->to_kill = darwin_kill_inferior;
darwin_ops->to_interrupt = darwin_interrupt;
darwin_ops->to_resume = darwin_resume_to;
darwin_ops->to_thread_alive = darwin_thread_alive;
darwin_ops->to_pid_to_str = darwin_pid_to_str;
darwin_ops->to_pid_to_exec_file = darwin_pid_to_exec_file;
darwin_ops->to_load = NULL;
darwin_ops->to_xfer_partial = darwin_xfer_partial;
darwin_ops->to_supports_multi_process = darwin_supports_multi_process;
darwin_ops->to_get_ada_task_ptid = darwin_get_ada_task_ptid;
darwin_complete_target (darwin_ops);
add_target (darwin_ops);
inferior_debug (2, _("GDB task: 0x%lx, pid: %d\n"),
(unsigned long) mach_task_self (), getpid ());

View File

@ -17,9 +17,50 @@
#ifndef __DARWIN_NAT_H__
#define __DARWIN_NAT_H__
#include "inf-child.h"
#include <mach/mach.h>
#include "gdbthread.h"
/* This needs to be overridden by the platform specific nat code. */
class darwin_nat_target : public inf_child_target
{
void create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty);
void attach (const char *, int) override;
void detach (inferior *, int) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void mourn_inferior () override;
void kill () override;
void interrupt () override;
void resume (ptid_t, int , enum gdb_signal) override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
char *pid_to_exec_file (int pid) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
int supports_multi_process () override;
ptid_t get_ada_task_ptid (long lwp, long thread) override;
};
/* Describe the mach exception handling state for a task. This state is saved
before being changed and restored when a process is detached.
For more information on these fields see task_get_exception_ports manual
@ -158,11 +199,6 @@ extern void mach_check_error (kern_return_t ret, const char *file,
void darwin_set_sstep (thread_t thread, int enable);
/* This one is called in darwin-nat.c, but needs to be provided by the
platform specific nat code. It allows each platform to add platform specific
stuff to the darwin_ops. */
extern void darwin_complete_target (struct target_ops *target);
void darwin_check_osabi (darwin_inferior *inf, thread_t thread);
#endif /* __DARWIN_NAT_H__ */

View File

@ -836,8 +836,7 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p)
if (target_read_memory (pointer_address, buf, ptr_size) != 0)
continue;
addr = extract_typed_address (buf, ptr_type);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
&current_target);
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, target_stack);
addr = gdbarch_addr_bits_remove (gdbarch, addr);
if (elf_gnu_ifunc_record_cache (name, addr))
@ -904,13 +903,12 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc)
parameter. FUNCTION is the function entry address. ADDRESS may be a
function descriptor. */
target_auxv_search (&current_target, AT_HWCAP, &hwcap);
target_auxv_search (target_stack, AT_HWCAP, &hwcap);
hwcap_val = value_from_longest (builtin_type (gdbarch)
->builtin_unsigned_long, hwcap);
address_val = call_function_by_hand (function, NULL, 1, &hwcap_val);
address = value_as_address (address_val);
address = gdbarch_convert_from_func_ptr_addr (gdbarch, address,
&current_target);
address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, target_stack);
address = gdbarch_addr_bits_remove (gdbarch, address);
if (name_at_pc)
@ -1017,7 +1015,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
resolved_address = value_as_address (value);
resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
resolved_address,
&current_target);
target_stack);
resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc);
gdb_assert (current_program_space == b->pspace || b->pspace == NULL);

View File

@ -1747,7 +1747,7 @@ evaluate_subexp_standard (struct type *expect_type,
/* The address might point to a function descriptor;
resolve it to the actual code address instead. */
addr = gdbarch_convert_from_func_ptr_addr (exp->gdbarch, addr,
&current_target);
target_stack);
/* Is it a high_level symbol? */
sym = find_pc_function (addr);

View File

@ -39,7 +39,11 @@ print_flush (void)
deprecated_error_begin_hook ();
gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
if (target_supports_terminal_ours ())
/* While normally there's always something pushed on the target
stack, the NULL check is needed here because we can get here very
early during startup, before the target stack is first
initialized. */
if (target_stack != NULL && target_supports_terminal_ours ())
{
term_state.emplace ();
target_terminal::ours_for_output ();

View File

@ -49,15 +49,43 @@
void (*deprecated_file_changed_hook) (const char *);
/* Prototypes for local functions */
static void exec_files_info (struct target_ops *);
static void init_exec_ops (void);
/* The target vector for executable files. */
static struct target_ops exec_ops;
struct exec_target final : public target_ops
{
exec_target ()
{ to_stratum = file_stratum; }
const char *shortname () override
{ return "exec"; }
const char *longname () override
{ return _("Local exec file"); }
const char *doc () override
{
return _("\
Use an executable file as a target.\n\
Specify the filename of the executable file.");
}
void open (const char *, int) override;
void close () override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
struct target_section_table *get_section_table () override;
void files_info () override;
int has_memory () override;
char *make_corefile_notes (bfd *, int *) override;
int find_memory_regions (find_memory_region_ftype func, void *data) override;
};
static exec_target exec_ops;
/* Whether to open exec and core files read-only or read-write. */
@ -71,8 +99,8 @@ show_write_files (struct ui_file *file, int from_tty,
}
static void
exec_open (const char *args, int from_tty)
void
exec_target::open (const char *args, int from_tty)
{
target_preopen (from_tty);
exec_file_attach (args, from_tty);
@ -105,8 +133,8 @@ exec_close (void)
/* This is the target_close implementation. Clears all target
sections and closes all executable bfds from all program spaces. */
static void
exec_close_1 (struct target_ops *self)
void
exec_target::close ()
{
struct program_space *ss;
scoped_restore_current_program_space restore_pspace;
@ -119,17 +147,7 @@ exec_close_1 (struct target_ops *self)
}
}
void
exec_file_clear (int from_tty)
{
/* Remove exec file. */
exec_close ();
if (from_tty)
printf_unfiltered (_("No executable file now.\n"));
}
/* See exec.h. */
/* See gdbcore.h. */
void
try_open_exec_file (const char *exec_file_host, struct inferior *inf,
@ -846,19 +864,19 @@ section_table_xfer_memory_partial (gdb_byte *readbuf, const gdb_byte *writebuf,
return TARGET_XFER_EOF; /* We can't help. */
}
static struct target_section_table *
exec_get_section_table (struct target_ops *ops)
struct target_section_table *
exec_target::get_section_table ()
{
return current_target_sections;
}
static enum target_xfer_status
exec_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
exec_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
struct target_section_table *table = target_get_section_table (ops);
struct target_section_table *table = get_section_table ();
if (object == TARGET_OBJECT_MEMORY)
return section_table_xfer_memory_partial (readbuf, writebuf,
@ -940,8 +958,8 @@ print_section_info (struct target_section_table *t, bfd *abfd)
}
}
static void
exec_files_info (struct target_ops *t)
void
exec_target::files_info ()
{
if (exec_bfd)
print_section_info (current_target_sections, exec_bfd);
@ -981,7 +999,7 @@ set_section_command (const char *args, int from_tty)
p->addr += offset;
p->endaddr += offset;
if (from_tty)
exec_files_info (&exec_ops);
exec_ops.files_info ();
return;
}
}
@ -1013,29 +1031,8 @@ exec_set_section_address (const char *filename, int index, CORE_ADDR address)
}
}
/* If mourn is being called in all the right places, this could be say
`gdb internal error' (since generic_mourn calls
breakpoint_init_inferior). */
static int
ignore (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return 0;
}
/* Implement the to_remove_breakpoint method. */
static int
exec_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
{
return 0;
}
static int
exec_has_memory (struct target_ops *ops)
int
exec_target::has_memory ()
{
/* We can provide memory if we have any file/target sections to read
from. */
@ -1043,34 +1040,16 @@ exec_has_memory (struct target_ops *ops)
!= current_target_sections->sections_end);
}
static char *
exec_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
char *
exec_target::make_corefile_notes (bfd *obfd, int *note_size)
{
error (_("Can't create a corefile"));
}
/* Fill in the exec file target vector. Very few entries need to be
defined. */
static void
init_exec_ops (void)
int
exec_target::find_memory_regions (find_memory_region_ftype func, void *data)
{
exec_ops.to_shortname = "exec";
exec_ops.to_longname = "Local exec file";
exec_ops.to_doc = "Use an executable file as a target.\n\
Specify the filename of the executable file.";
exec_ops.to_open = exec_open;
exec_ops.to_close = exec_close_1;
exec_ops.to_xfer_partial = exec_xfer_partial;
exec_ops.to_get_section_table = exec_get_section_table;
exec_ops.to_files_info = exec_files_info;
exec_ops.to_insert_breakpoint = ignore;
exec_ops.to_remove_breakpoint = exec_remove_breakpoint;
exec_ops.to_stratum = file_stratum;
exec_ops.to_has_memory = exec_has_memory;
exec_ops.to_make_corefile_notes = exec_make_note_section;
exec_ops.to_find_memory_regions = objfile_find_memory_regions;
exec_ops.to_magic = OPS_MAGIC;
return objfile_find_memory_regions (this, func, data);
}
void
@ -1078,8 +1057,6 @@ _initialize_exec (void)
{
struct cmd_list_element *c;
init_exec_ops ();
if (!dbx_commands)
{
c = add_cmd ("file", class_files, file_command, _("\

View File

@ -46,19 +46,11 @@
#include <list>
#ifdef TRAP_BRKPT
/* MIPS does not set si_code for SIGTRAP. sparc64 reports
non-standard values in si_code for SIGTRAP. */
# if !defined(__mips__) && !defined(__sparc64__)
# define USE_SIGTRAP_SIGINFO
# endif
#endif
/* Return the name of a file that can be opened to get the symbols for
the child process identified by PID. */
static char *
fbsd_pid_to_exec_file (struct target_ops *self, int pid)
char *
fbsd_nat_target::pid_to_exec_file (int pid)
{
ssize_t len;
static char buf[PATH_MAX];
@ -96,9 +88,9 @@ fbsd_pid_to_exec_file (struct target_ops *self, int pid)
calling FUNC for each memory region. OBFD is passed as the last
argument to FUNC. */
static int
fbsd_find_memory_regions (struct target_ops *self,
find_memory_region_ftype func, void *obfd)
int
fbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
void *obfd)
{
pid_t pid = ptid_get_pid (inferior_ptid);
struct kinfo_vmentry *kve;
@ -170,9 +162,9 @@ fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end,
calling FUNC for each memory region. OBFD is passed as the last
argument to FUNC. */
static int
fbsd_find_memory_regions (struct target_ops *self,
find_memory_region_ftype func, void *obfd)
int
fbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
void *obfd)
{
pid_t pid = ptid_get_pid (inferior_ptid);
unsigned long start, end, size;
@ -259,11 +251,10 @@ fbsd_fetch_kinfo_proc (pid_t pid, struct kinfo_proc *kp)
return (sysctl (mib, 4, kp, &len, NULL, 0) == 0);
}
/* Implement the "to_info_proc target_ops" method. */
/* Implement the "info_proc" target_ops method. */
static void
fbsd_info_proc (struct target_ops *ops, const char *args,
enum info_proc_what what)
bool
fbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
{
#ifdef HAVE_KINFO_GETFILE
gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl;
@ -378,7 +369,7 @@ fbsd_info_proc (struct target_ops *ops, const char *args,
}
#endif
if (exe == NULL)
exe = fbsd_pid_to_exec_file (ops, pid);
exe = pid_to_exec_file (pid);
if (exe != NULL)
printf_filtered ("exe = '%s'\n", exe);
else
@ -539,17 +530,11 @@ fbsd_info_proc (struct target_ops *ops, const char *args,
printf_filtered ("\n");
}
}
return true;
}
#ifdef KERN_PROC_AUXV
static enum target_xfer_status (*super_xfer_partial) (struct target_ops *ops,
enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset,
ULONGEST len,
ULONGEST *xfered_len);
#ifdef PT_LWPINFO
/* Return the size of siginfo for the current inferior. */
@ -680,13 +665,14 @@ fbsd_convert_siginfo (siginfo_t *si)
}
#endif
/* Implement the "to_xfer_partial target_ops" method. */
/* Implement the "xfer_partial" target_ops method. */
static enum target_xfer_status
fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
fbsd_nat_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
pid_t pid = ptid_get_pid (inferior_ptid);
@ -766,8 +752,9 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
return TARGET_XFER_E_IO;
}
default:
return super_xfer_partial (ops, object, annex, readbuf, writebuf, offset,
len, xfered_len);
return inf_ptrace_target::xfer_partial (object, annex,
readbuf, writebuf, offset,
len, xfered_len);
}
}
#endif
@ -776,15 +763,6 @@ fbsd_xfer_partial (struct target_ops *ops, enum target_object object,
static int debug_fbsd_lwp;
static int debug_fbsd_nat;
static void (*super_resume) (struct target_ops *,
ptid_t,
int,
enum gdb_signal);
static ptid_t (*super_wait) (struct target_ops *,
ptid_t,
struct target_waitstatus *,
int);
static void
show_fbsd_lwp_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@ -829,8 +807,8 @@ show_fbsd_nat_debug (struct ui_file *file, int from_tty,
/* Return true if PTID is still active in the inferior. */
static int
fbsd_thread_alive (struct target_ops *ops, ptid_t ptid)
int
fbsd_nat_target::thread_alive (ptid_t ptid)
{
if (ptid_lwp_p (ptid))
{
@ -851,8 +829,8 @@ fbsd_thread_alive (struct target_ops *ops, ptid_t ptid)
/* Convert PTID to a string. Returns the string in a static
buffer. */
static const char *
fbsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
fbsd_nat_target::pid_to_str (ptid_t ptid)
{
lwpid_t lwp;
@ -873,8 +851,8 @@ fbsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
/* Return the name assigned to a thread by an application. Returns
the string in a static buffer. */
static const char *
fbsd_thread_name (struct target_ops *self, struct thread_info *thr)
const char *
fbsd_nat_target::thread_name (struct thread_info *thr)
{
struct ptrace_lwpinfo pl;
struct kinfo_proc kp;
@ -984,10 +962,10 @@ fbsd_add_threads (pid_t pid)
}
}
/* Implement the "to_update_thread_list" target_ops method. */
/* Implement the "update_thread_list" target_ops method. */
static void
fbsd_update_thread_list (struct target_ops *ops)
void
fbsd_nat_target::update_thread_list ()
{
#ifdef PT_LWP_EVENTS
/* With support for thread events, threads are added/deleted from the
@ -1102,11 +1080,10 @@ fbsd_next_vfork_done (void)
#endif
#endif
/* Implement the "to_resume" target_ops method. */
/* Implement the "resume" target_ops method. */
static void
fbsd_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signo)
void
fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
{
#if defined(TDP_RFPPWAIT) && !defined(PTRACE_VFORK)
pid_t pid;
@ -1193,7 +1170,7 @@ fbsd_resume (struct target_ops *ops,
}
ptid = ptid_t (ptid.pid ());
#endif
super_resume (ops, ptid, step, signo);
inf_ptrace_target::resume (ptid, step, signo);
}
#ifdef USE_SIGTRAP_SIGINFO
@ -1202,8 +1179,7 @@ fbsd_resume (struct target_ops *ops,
core, return true. */
static bool
fbsd_handle_debug_trap (struct target_ops *ops, ptid_t ptid,
const struct ptrace_lwpinfo &pl)
fbsd_handle_debug_trap (ptid_t ptid, const struct ptrace_lwpinfo &pl)
{
/* Ignore traps without valid siginfo or for signals other than
@ -1250,10 +1226,9 @@ fbsd_handle_debug_trap (struct target_ops *ops, ptid_t ptid,
process ID of the child, or MINUS_ONE_PTID in case of error; store
the status in *OURSTATUS. */
static ptid_t
fbsd_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus,
int target_options)
ptid_t
fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int target_options)
{
ptid_t wptid;
@ -1267,7 +1242,7 @@ fbsd_wait (struct target_ops *ops,
return wptid;
}
#endif
wptid = super_wait (ops, ptid, ourstatus, target_options);
wptid = inf_ptrace_target::wait (ptid, ourstatus, target_options);
if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
{
struct ptrace_lwpinfo pl;
@ -1296,7 +1271,7 @@ fbsd_wait (struct target_ops *ops,
if (pl.pl_flags & PL_FLAG_EXITED)
{
/* If GDB attaches to a multi-threaded process, exiting
threads might be skipped during fbsd_post_attach that
threads might be skipped during post_attach that
have not yet reported their PL_FLAG_EXITED event.
Ignore EXITED events for an unknown LWP. */
if (in_thread_list (wptid))
@ -1426,13 +1401,13 @@ fbsd_wait (struct target_ops *ops,
{
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname
= xstrdup (fbsd_pid_to_exec_file (NULL, pid));
= xstrdup (pid_to_exec_file (pid));
return wptid;
}
#endif
#ifdef USE_SIGTRAP_SIGINFO
if (fbsd_handle_debug_trap (ops, wptid, pl))
if (fbsd_handle_debug_trap (wptid, pl))
return wptid;
#endif
@ -1475,10 +1450,10 @@ fbsd_wait (struct target_ops *ops,
}
#ifdef USE_SIGTRAP_SIGINFO
/* Implement the "to_stopped_by_sw_breakpoint" target_ops method. */
/* Implement the "stopped_by_sw_breakpoint" target_ops method. */
static int
fbsd_stopped_by_sw_breakpoint (struct target_ops *ops)
int
fbsd_nat_target::stopped_by_sw_breakpoint ()
{
struct ptrace_lwpinfo pl;
@ -1491,32 +1466,22 @@ fbsd_stopped_by_sw_breakpoint (struct target_ops *ops)
&& pl.pl_siginfo.si_code == TRAP_BRKPT);
}
/* Implement the "to_supports_stopped_by_sw_breakpoint" target_ops
/* Implement the "supports_stopped_by_sw_breakpoint" target_ops
method. */
static int
fbsd_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
int
fbsd_nat_target::supports_stopped_by_sw_breakpoint ()
{
return 1;
}
/* Implement the "to_supports_stopped_by_hw_breakpoint" target_ops
method. */
static int
fbsd_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
{
return ops->to_stopped_by_hw_breakpoint != NULL;
}
#endif
#ifdef TDP_RFPPWAIT
/* Target hook for follow_fork. On entry and at return inferior_ptid is
the ptid of the followed inferior. */
static int
fbsd_follow_fork (struct target_ops *ops, int follow_child,
int detach_fork)
int
fbsd_nat_target::follow_fork (int follow_child, int detach_fork)
{
if (!follow_child && detach_fork)
{
@ -1562,43 +1527,43 @@ fbsd_follow_fork (struct target_ops *ops, int follow_child,
return 0;
}
static int
fbsd_insert_fork_catchpoint (struct target_ops *self, int pid)
int
fbsd_nat_target::insert_fork_catchpoint (int pid)
{
return 0;
}
static int
fbsd_remove_fork_catchpoint (struct target_ops *self, int pid)
int
fbsd_nat_target::remove_fork_catchpoint (int pid)
{
return 0;
}
static int
fbsd_insert_vfork_catchpoint (struct target_ops *self, int pid)
int
fbsd_nat_target::insert_vfork_catchpoint (int pid)
{
return 0;
}
static int
fbsd_remove_vfork_catchpoint (struct target_ops *self, int pid)
int
fbsd_nat_target::remove_vfork_catchpoint (int pid)
{
return 0;
}
#endif
/* Implement the "to_post_startup_inferior" target_ops method. */
/* Implement the "post_startup_inferior" target_ops method. */
static void
fbsd_post_startup_inferior (struct target_ops *self, ptid_t pid)
void
fbsd_nat_target::post_startup_inferior (ptid_t pid)
{
fbsd_enable_proc_events (ptid_get_pid (pid));
}
/* Implement the "to_post_attach" target_ops method. */
/* Implement the "post_attach" target_ops method. */
static void
fbsd_post_attach (struct target_ops *self, int pid)
void
fbsd_nat_target::post_attach (int pid)
{
fbsd_enable_proc_events (pid);
fbsd_add_threads (pid);
@ -1608,24 +1573,24 @@ fbsd_post_attach (struct target_ops *self, int pid)
/* If the FreeBSD kernel supports PL_FLAG_EXEC, then traced processes
will always stop after exec. */
static int
fbsd_insert_exec_catchpoint (struct target_ops *self, int pid)
int
fbsd_nat_target::insert_exec_catchpoint (int pid)
{
return 0;
}
static int
fbsd_remove_exec_catchpoint (struct target_ops *self, int pid)
int
fbsd_nat_target::remove_exec_catchpoint (int pid)
{
return 0;
}
#endif
#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE
static int
fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, bool needed,
int any_count,
gdb::array_view<const int> syscall_counts)
int
fbsd_nat_target::set_syscall_catchpoint (int pid, bool needed,
int any_count,
gdb::array_view<const int> syscall_counts)
{
/* Ignore the arguments. inf-ptrace.c will use PT_SYSCALL which
@ -1636,55 +1601,6 @@ fbsd_set_syscall_catchpoint (struct target_ops *self, int pid, bool needed,
#endif
#endif
void
fbsd_nat_add_target (struct target_ops *t)
{
t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
t->to_find_memory_regions = fbsd_find_memory_regions;
t->to_info_proc = fbsd_info_proc;
#ifdef KERN_PROC_AUXV
super_xfer_partial = t->to_xfer_partial;
t->to_xfer_partial = fbsd_xfer_partial;
#endif
#ifdef PT_LWPINFO
t->to_thread_alive = fbsd_thread_alive;
t->to_pid_to_str = fbsd_pid_to_str;
#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME
t->to_thread_name = fbsd_thread_name;
#endif
t->to_update_thread_list = fbsd_update_thread_list;
t->to_has_thread_control = tc_schedlock;
super_resume = t->to_resume;
t->to_resume = fbsd_resume;
super_wait = t->to_wait;
t->to_wait = fbsd_wait;
t->to_post_startup_inferior = fbsd_post_startup_inferior;
t->to_post_attach = fbsd_post_attach;
#ifdef USE_SIGTRAP_SIGINFO
t->to_stopped_by_sw_breakpoint = fbsd_stopped_by_sw_breakpoint;
t->to_supports_stopped_by_sw_breakpoint
= fbsd_supports_stopped_by_sw_breakpoint;
t->to_supports_stopped_by_hw_breakpoint
= fbsd_supports_stopped_by_hw_breakpoint;
#endif
#ifdef TDP_RFPPWAIT
t->to_follow_fork = fbsd_follow_fork;
t->to_insert_fork_catchpoint = fbsd_insert_fork_catchpoint;
t->to_remove_fork_catchpoint = fbsd_remove_fork_catchpoint;
t->to_insert_vfork_catchpoint = fbsd_insert_vfork_catchpoint;
t->to_remove_vfork_catchpoint = fbsd_remove_vfork_catchpoint;
#endif
#ifdef PL_FLAG_EXEC
t->to_insert_exec_catchpoint = fbsd_insert_exec_catchpoint;
t->to_remove_exec_catchpoint = fbsd_remove_exec_catchpoint;
#endif
#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE
t->to_set_syscall_catchpoint = fbsd_set_syscall_catchpoint;
#endif
#endif
add_target (t);
}
void
_initialize_fbsd_nat (void)
{

View File

@ -20,8 +20,81 @@
#ifndef FBSD_NAT_H
#define FBSD_NAT_H
/* Register the customized FreeBSD target. This should be used
instead of calling add_target directly. */
extern void fbsd_nat_add_target (struct target_ops *);
#include "inf-ptrace.h"
#ifdef TRAP_BRKPT
/* MIPS does not set si_code for SIGTRAP. sparc64 reports
non-standard values in si_code for SIGTRAP. */
# if !defined(__mips__) && !defined(__sparc64__)
# define USE_SIGTRAP_SIGINFO
# endif
#endif
/* A prototype FreeBSD target. */
class fbsd_nat_target : public inf_ptrace_target
{
public:
char *pid_to_exec_file (int pid) override;
int find_memory_regions (find_memory_region_ftype func, void *data);
bool info_proc (const char *, enum info_proc_what);
#ifdef KERN_PROC_AUXV
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
#endif
#ifdef PT_LWPINFO
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME
const char *thread_name (struct thread_info *) override;
#endif
void update_thread_list () override;
thread_control_capabilities get_thread_control_capabilities () override
{ return tc_schedlock; }
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void post_startup_inferior (ptid_t) override;
void post_attach (int) override;
#ifdef USE_SIGTRAP_SIGINFO
int supports_stopped_by_sw_breakpoint () override;
int stopped_by_sw_breakpoint () override;
#endif
#ifdef TDP_RFPPWAIT
int follow_fork (int, int) override;
int insert_fork_catchpoint (int) override;
int remove_fork_catchpoint (int) override;
int insert_vfork_catchpoint (int) override;
int remove_vfork_catchpoint (int) override;
#endif
#ifdef PL_FLAG_EXEC
int insert_exec_catchpoint (int) override;
int remove_exec_catchpoint (int) override;
#endif
#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE
int set_syscall_catchpoint (int, bool, int, gdb::array_view<const int>)
override;
#endif
#endif /* PT_LWPINFO */
};
#endif /* fbsd-nat.h */

View File

@ -2217,7 +2217,7 @@ inside_main_func (struct frame_info *this_frame)
returned. */
maddr = gdbarch_convert_from_func_ptr_addr (get_frame_arch (this_frame),
BMSYMBOL_VALUE_ADDRESS (msymbol),
&current_target);
target_stack);
return maddr == get_frame_func (this_frame);
}

View File

@ -71,8 +71,8 @@ register_to_value_test (struct gdbarch *gdbarch)
/* Error out if debugging something, because we're going to push the
test target, which would pop any existing target. */
if (current_target.to_stratum >= process_stratum)
error (_("target already pushed"));
if (target_stack->to_stratum >= process_stratum)
error (_("target already pushed"));
/* Create a mock environment. An inferior with a thread, with a
process_stratum target pushed. */

View File

@ -135,7 +135,9 @@ extern void specify_exec_file_hook (void (*hook) (const char *filename));
extern bfd *core_bfd;
extern struct target_ops *core_target;
/* corelow.c target. It is never NULL after GDB initialization. */
extern struct target_ops *the_core_target;
/* Whether to open exec and core files read-only or read-write. */
@ -153,8 +155,6 @@ extern void exec_file_attach (const char *filename, int from_tty);
extern void exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty);
extern void exec_file_clear (int from_tty);
extern void validate_files (void);
/* The current default bfd target. */

View File

@ -1461,9 +1461,10 @@ extern "C" int notify_server (mach_msg_header_t *, mach_msg_header_t *);
extern "C" int process_reply_server (mach_msg_header_t *, mach_msg_header_t *);
/* Wait for something to happen in the inferior, returning what in STATUS. */
static ptid_t
gnu_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
gnu_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
struct msg
{
@ -1998,9 +1999,8 @@ port_msgs_queued (mach_port_t port)
still unprocessed from the last resume we did (any given resume may result
in multiple events returned by wait). */
static void
gnu_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal sig)
void
gnu_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
{
struct proc *step_thread = 0;
int resume_all;
@ -2075,8 +2075,8 @@ gnu_resume (struct target_ops *ops,
}
static void
gnu_kill_inferior (struct target_ops *ops)
void
gnu_nat_target::kill ()
{
struct proc *task = gnu_current_inf->task;
@ -2090,12 +2090,12 @@ gnu_kill_inferior (struct target_ops *ops)
}
/* Clean up after the inferior dies. */
static void
gnu_mourn_inferior (struct target_ops *ops)
void
gnu_nat_target::mourn_inferior ()
{
inf_debug (gnu_current_inf, "rip");
inf_detach (gnu_current_inf);
inf_child_mourn_inferior (ops);
inf_child_target::mourn_inferior ();
}
@ -2131,11 +2131,11 @@ gnu_ptrace_me (void)
trace_start_error_with_name ("ptrace");
}
static void
gnu_create_inferior (struct target_ops *ops,
const char *exec_file, const std::string &allargs,
char **env,
int from_tty)
void
gnu_nat_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env,
int from_tty)
{
struct inf *inf = cur_inf ();
int pid;
@ -2155,7 +2155,7 @@ gnu_create_inferior (struct target_ops *ops,
inf_attach (inf, pid);
push_target (ops);
push_target (this);
inf->pending_execs = 1;
inf->nomsg = 1;
@ -2190,8 +2190,8 @@ gnu_create_inferior (struct target_ops *ops,
/* Attach to process PID, then initialize for debugging it
and wait for the trace-trap that results from attaching. */
static void
gnu_attach (struct target_ops *ops, const char *args, int from_tty)
void
gnu_nat_target::attach (const char *args, int from_tty)
{
int pid;
char *exec_file;
@ -2220,7 +2220,7 @@ gnu_attach (struct target_ops *ops, const char *args, int from_tty)
inf_attach (inf, pid);
push_target (ops);
push_target (this);
inferior = current_inferior ();
inferior_appeared (inferior, pid);
@ -2254,8 +2254,8 @@ gnu_attach (struct target_ops *ops, const char *args, int from_tty)
to work, it may be necessary for the process to have been
previously attached. It *might* work if the program was
started via fork. */
static void
gnu_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
gnu_nat_target::detach (inferior *inf, int from_tty)
{
int pid;
@ -2282,14 +2282,14 @@ gnu_detach (struct target_ops *ops, inferior *inf, int from_tty)
}
static void
gnu_stop (struct target_ops *self, ptid_t ptid)
void
gnu_nat_target::stop (ptid_t ptid)
{
error (_("to_stop target function not implemented"));
error (_("stop target function not implemented"));
}
static int
gnu_thread_alive (struct target_ops *ops, ptid_t ptid)
int
gnu_nat_target::thread_alive (ptid_t ptid)
{
inf_update_procs (gnu_current_inf);
return !!inf_tid_to_thread (gnu_current_inf,
@ -2599,11 +2599,11 @@ gnu_xfer_auxv (gdb_byte *readbuf, const gdb_byte *writebuf,
/* Target to_xfer_partial implementation. */
static enum target_xfer_status
gnu_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
enum target_xfer_status
gnu_nat_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
@ -2617,9 +2617,10 @@ gnu_xfer_partial (struct target_ops *ops, enum target_object object,
}
/* Call FUNC on each memory region in the task. */
static int
gnu_find_memory_regions (struct target_ops *self,
find_memory_region_ftype func, void *data)
int
gnu_nat_target::find_memory_regions (find_memory_region_ftype func,
void *data)
{
kern_return_t err;
task_t task;
@ -2711,8 +2712,8 @@ proc_string (struct proc *proc)
return tid_str;
}
static const char *
gnu_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
gnu_nat_target::pid_to_str (ptid_t ptid)
{
struct inf *inf = gnu_current_inf;
int tid = ptid_get_lwp (ptid);
@ -2729,32 +2730,6 @@ gnu_pid_to_str (struct target_ops *ops, ptid_t ptid)
}
}
/* Create a prototype generic GNU/Hurd target. The client can
override it with local methods. */
struct target_ops *
gnu_target (void)
{
struct target_ops *t = inf_child_target ();
t->to_attach = gnu_attach;
t->to_attach_no_wait = 1;
t->to_detach = gnu_detach;
t->to_resume = gnu_resume;
t->to_wait = gnu_wait;
t->to_xfer_partial = gnu_xfer_partial;
t->to_find_memory_regions = gnu_find_memory_regions;
t->to_kill = gnu_kill_inferior;
t->to_create_inferior = gnu_create_inferior;
t->to_mourn_inferior = gnu_mourn_inferior;
t->to_thread_alive = gnu_thread_alive;
t->to_pid_to_str = gnu_pid_to_str;
t->to_stop = gnu_stop;
return t;
}
/* User task commands. */

View File

@ -103,8 +103,36 @@ extern int gnu_debug_flag;
fprintf_unfiltered (gdb_stdlog, "%s:%d: " msg "\r\n", \
__FILE__ , __LINE__ , ##args); } while (0)
/* Create a prototype generic GNU/Hurd target. The client can
override it with local methods. */
struct target_ops *gnu_target (void);
/* A prototype generic GNU/Hurd target. The client can override it
with local methods. */
struct gnu_nat_target : public inf_child_target
{
void attach (const char *, int) override;
bool attach_no_wait () override
{ return true; }
void detach (inferior *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
int find_memory_regions (find_memory_region_ftype func, void *data)
override;
void kill () override;
void create_inferior (const char *, const std::string &,
char **, int) override;
void mourn_inferior () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
void stop (ptid_t) override;
};
#endif /* __GNU_NAT_H__ */

View File

@ -1217,7 +1217,7 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
of the real function from the function descriptor before passing on
the address to other layers of GDB. */
func_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, method_stop_pc,
&current_target);
target_stack);
if (func_addr != 0)
method_stop_pc = func_addr;

View File

@ -232,7 +232,6 @@ static int dr_ref_count[4];
#define SOME_PID 42
static int prog_has_started = 0;
static void go32_mourn_inferior (struct target_ops *ops);
#define r_ofs(x) (offsetof(TSS,x))
@ -335,8 +334,56 @@ static struct {
{GDB_SIGNAL_LAST, -1}
};
static void
go32_attach (struct target_ops *ops, const char *args, int from_tty)
/* The go32 target. */
struct go32_nat_target final : public x86_nat_target<inf_child_target>
{
void attach (const char *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void files_info () override;
void terminal_init () override;
void terminal_inferior () override;
void terminal_ours_for_output () override;
void terminal_ours () override;
void terminal_info (const char *, int) override;
void pass_ctrlc () override;
void kill () override;
void create_inferior (const char *, const std::string &,
char **, int) override;
void mourn_inferior () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
};
static go32_nat_target the_go32_nat_target;
void
go32_nat_target::attach (const char *args, int from_tty)
{
error (_("\
You cannot attach to a running program on this platform.\n\
@ -346,9 +393,8 @@ Use the `run' command to run DJGPP programs."));
static int resume_is_step;
static int resume_signal = -1;
static void
go32_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal siggnal)
void
go32_nat_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
{
int i;
@ -371,9 +417,9 @@ go32_resume (struct target_ops *ops,
static char child_cwd[FILENAME_MAX];
static ptid_t
go32_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
go32_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
int i;
unsigned char saved_opcode;
@ -505,9 +551,8 @@ fetch_register (struct regcache *regcache, int regno)
_("Invalid register no. %d in fetch_register."), regno);
}
static void
go32_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
go32_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
if (regno >= 0)
fetch_register (regcache, regno);
@ -536,9 +581,8 @@ store_register (const struct regcache *regcache, int regno)
_("Invalid register no. %d in store_register."), regno);
}
static void
go32_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
go32_nat_target::store_registers (struct regcache *regcache, int regno)
{
unsigned r;
@ -598,11 +642,12 @@ go32_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
/* Target to_xfer_partial implementation. */
static enum target_xfer_status
go32_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
enum target_xfer_status
go32_nat_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len,
ULONGEST *xfered_len)
{
switch (object)
{
@ -610,30 +655,30 @@ go32_xfer_partial (struct target_ops *ops, enum target_object object,
return go32_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
default:
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
readbuf, writebuf, offset, len,
xfered_len);
return this->beneath->xfer_partial (object, annex,
readbuf, writebuf, offset, len,
xfered_len);
}
}
static cmdline_t child_cmd; /* Parsed child's command line kept here. */
static void
go32_files_info (struct target_ops *target)
void
go32_nat_target::files_info ()
{
printf_unfiltered ("You are running a DJGPP V2 program.\n");
}
static void
go32_kill_inferior (struct target_ops *ops)
void
go32_nat_target::kill_inferior ()
{
go32_mourn_inferior (ops);
mourn_inferior ();
}
static void
go32_create_inferior (struct target_ops *ops,
const char *exec_file,
const std::string &allargs, char **env, int from_tty)
void
go32_nat_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
extern char **environ;
jmp_buf start_state;
@ -711,8 +756,8 @@ go32_create_inferior (struct target_ops *ops,
inf = current_inferior ();
inferior_appeared (inf, SOME_PID);
if (!target_is_pushed (ops))
push_target (ops);
if (!target_is_pushed (this))
push_target (this);
add_thread_silent (inferior_ptid);
@ -721,8 +766,8 @@ go32_create_inferior (struct target_ops *ops,
prog_has_started = 1;
}
static void
go32_mourn_inferior (struct target_ops *ops)
void
go32_nat_target::mourn_inferior ()
{
ptid_t ptid;
@ -747,7 +792,7 @@ go32_mourn_inferior (struct target_ops *ops)
prog_has_started = 0;
generic_mourn_inferior ();
inf_child_maybe_unpush_target (ops);
maybe_unpush_target ();
}
/* Hardware watchpoint support. */
@ -852,15 +897,15 @@ static int inf_terminal_mode;
second call will always see GDB's own cooked terminal. */
static int terminal_is_ours = 1;
static void
go32_terminal_init (struct target_ops *self)
void
go32_nat_target::terminal_init ()
{
inf_mode_valid = 0; /* Reinitialize, in case they are restarting child. */
terminal_is_ours = 1;
}
static void
go32_terminal_info (struct target_ops *self, const char *args, int from_tty)
void
go32_nat_target::terminal_info (const char *args, int from_tty)
{
printf_unfiltered ("Inferior's terminal is in %s mode.\n",
!inf_mode_valid
@ -889,8 +934,8 @@ go32_terminal_info (struct target_ops *self, const char *args, int from_tty)
#endif
}
static void
go32_terminal_inferior (struct target_ops *self)
void
go32_nat_target::terminal_inferior ()
{
/* Redirect standard handles as child wants them. */
errno = 0;
@ -910,8 +955,8 @@ go32_terminal_inferior (struct target_ops *self)
}
}
static void
go32_terminal_ours (struct target_ops *self)
void
go32_nat_target::terminal_ours ()
{
/* Switch to cooked mode on the gdb terminal and save the inferior
terminal mode to be restored when it is resumed. */
@ -937,52 +982,23 @@ go32_terminal_ours (struct target_ops *self)
}
}
static void
go32_pass_ctrlc (struct target_ops *self)
void
go32_nat_target::pass_ctrlc ()
{
}
static int
go32_thread_alive (struct target_ops *ops, ptid_t ptid)
int
go32_nat_target::thread_alive (ptid_t ptid)
{
return !ptid_equal (ptid, null_ptid);
}
static const char *
go32_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
go32_nat_target::pid_to_str (ptid_t ptid)
{
return normal_pid_to_str (ptid);
}
/* Create a go32 target. */
static struct target_ops *
go32_target (void)
{
struct target_ops *t = inf_child_target ();
t->to_attach = go32_attach;
t->to_resume = go32_resume;
t->to_wait = go32_wait;
t->to_fetch_registers = go32_fetch_registers;
t->to_store_registers = go32_store_registers;
t->to_xfer_partial = go32_xfer_partial;
t->to_files_info = go32_files_info;
t->to_terminal_init = go32_terminal_init;
t->to_terminal_inferior = go32_terminal_inferior;
t->to_terminal_ours_for_output = go32_terminal_ours;
t->to_terminal_ours = go32_terminal_ours;
t->to_terminal_info = go32_terminal_info;
t->to_pass_ctrlc = go32_pass_ctrlc;
t->to_kill = go32_kill_inferior;
t->to_create_inferior = go32_create_inferior;
t->to_mourn_inferior = go32_mourn_inferior;
t->to_thread_alive = go32_thread_alive;
t->to_pid_to_str = go32_pid_to_str;
return t;
}
/* Return the current DOS codepage number. */
static int
dos_codepage (void)
@ -2067,8 +2083,6 @@ go32_info_dos_command (const char *args, int from_tty)
void
_initialize_go32_nat (void)
{
struct target_ops *t = go32_target ();
x86_dr_low.set_control = go32_set_dr7;
x86_dr_low.set_addr = go32_set_dr;
x86_dr_low.get_status = go32_get_dr6;
@ -2076,8 +2090,7 @@ _initialize_go32_nat (void)
x86_dr_low.get_addr = go32_get_dr;
x86_set_debug_register_length (4);
x86_use_watchpoints (t);
add_target (t);
add_target (&the_go32_nat_target);
/* Initialize child's cwd as empty to be initialized when starting
the child. */

View File

@ -34,6 +34,16 @@
#include "hppa-tdep.h"
class hppa_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static hppa_linux_nat_target the_hppa_linux_nat_target;
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
@ -262,9 +272,9 @@ store_register (const struct regcache *regcache, int regno)
regno == -1, otherwise fetch all general registers or all floating
point registers depending upon the value of regno. */
static void
hppa_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
hppa_linux_nat_target::fetch_inferior_registers (struct regcache *regcache,
int regno)
{
if (-1 == regno)
{
@ -283,9 +293,8 @@ hppa_linux_fetch_inferior_registers (struct target_ops *ops,
regno == -1, otherwise store all general registers or all floating
point registers depending upon the value of regno. */
static void
hppa_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
hppa_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
if (-1 == regno)
{
@ -380,15 +389,7 @@ fill_fpregset (const struct regcache *regcache,
void
_initialize_hppa_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Add our register access methods. */
t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
t->to_store_registers = hppa_linux_store_inferior_registers;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_hppa_linux_nat_target;
add_target (&the_hppa_linux_nat_target);
}

View File

@ -30,6 +30,14 @@
#include "nbsd-nat.h"
class hppa_nbsd_nat_target final : public nbsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static hppa_nbsd_nat_target the_hppa_nbsd_nat_target;
static int
hppanbsd_gregset_supplies_p (int regnum)
{
@ -158,9 +166,8 @@ hppanbsd_collect_fpregset (struct regcache *regcache,
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers (including the floating-point registers). */
static void
hppanbsd_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
hppa_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -189,9 +196,8 @@ hppanbsd_fetch_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating-point registers). */
static void
hppanbsd_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
hppa_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -225,15 +231,5 @@ hppanbsd_store_registers (struct target_ops *ops,
void
_initialize_hppanbsd_nat (void)
{
struct target_ops *t;
/* Add some extra features to the ptrace target. */
t = inf_ptrace_target ();
t->to_fetch_registers = hppanbsd_fetch_registers;
t->to_store_registers = hppanbsd_store_registers;
t->to_pid_to_exec_file = nbsd_pid_to_exec_file;
add_target (t);
add_target (&the_hppa_nbsd_nat_target);
}

View File

@ -31,6 +31,14 @@
#include "obsd-nat.h"
struct hppa_obsd_nat_target final : public obsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static hppa_obsd_nat_target the_hppa_obsd_nat_target;
static int
hppaobsd_gregset_supplies_p (int regnum)
{
@ -185,9 +193,8 @@ hppaobsd_collect_fpregset (struct regcache *regcache,
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers (including the floating-point registers). */
static void
hppaobsd_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
hppa_obsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -215,9 +222,8 @@ hppaobsd_fetch_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating-point registers). */
static void
hppaobsd_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
hppa_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
if (regnum == -1 || hppaobsd_gregset_supplies_p (regnum))
{
@ -249,10 +255,5 @@ hppaobsd_store_registers (struct target_ops *ops,
void
_initialize_hppaobsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = hppaobsd_fetch_registers;
t->to_store_registers = hppaobsd_store_registers;
obsd_add_target (t);
add_target (&the_hppa_obsd_nat_target);
}

View File

@ -127,9 +127,8 @@ i386bsd_collect_gregset (const struct regcache *regcache,
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers (including the floating point registers). */
static void
i386bsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
i386bsd_fetch_inferior_registers (struct regcache *regcache, int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -191,9 +190,8 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating point registers). */
static void
i386bsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
i386bsd_store_inferior_registers (struct regcache *regcache, int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -267,20 +265,6 @@ i386bsd_store_inferior_registers (struct target_ops *ops,
}
}
/* Create a prototype *BSD/i386 target. The client can override it
with local methods. */
struct target_ops *
i386bsd_target (void)
{
struct target_ops *t;
t = x86bsd_target ();
t->to_fetch_registers = i386bsd_fetch_inferior_registers;
t->to_store_registers = i386bsd_store_inferior_registers;
return t;
}
void
_initialize_i386bsd_nat (void)
{

View File

@ -20,9 +20,23 @@
#ifndef I386_BSD_NAT_H
#define I386_BSD_NAT_H
/* Create a prototype *BSD/i386 target. The client can override it
with local methods. */
/* Helper functions. See definitions. */
extern void i386bsd_fetch_inferior_registers (struct regcache *regcache,
int regnum);
extern void i386bsd_store_inferior_registers (struct regcache *regcache,
int regnum);
extern struct target_ops *i386bsd_target (void);
/* A prototype *BSD/i386 target. */
template<typename BaseTarget>
class i386_bsd_nat_target : public x86bsd_nat_target<BaseTarget>
{
public:
void fetch_registers (struct regcache *regcache, int regnum) override
{ i386bsd_fetch_inferior_registers (regcache, regnum); }
void store_registers (struct regcache *regcache, int regnum) override
{ i386bsd_store_inferior_registers (regcache, regnum); }
};
#endif /* i386-bsd-nat.h */

View File

@ -43,12 +43,21 @@
#include "amd64-darwin-tdep.h"
#endif
struct i386_darwin_nat_target final : public x86_nat_target<darwin_nat_target>
{
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static struct i386_darwin_nat_target darwin_target;
/* Read register values from the inferior process.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
static void
i386_darwin_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
i386_darwin_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
thread_t current_thread = ptid_get_tid (regcache_get_ptid (regcache));
int fetched = 0;
@ -163,9 +172,9 @@ i386_darwin_fetch_inferior_registers (struct target_ops *ops,
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
static void
i386_darwin_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
i386_darwin_nat_target::store_registers (struct regcache *regcache,
int regno)
{
thread_t current_thread = ptid_get_tid (regcache_get_ptid (regcache));
struct gdbarch *gdbarch = regcache->arch ();
@ -628,7 +637,7 @@ darwin_set_sstep (thread_t thread, int enable)
}
void
darwin_complete_target (struct target_ops *target)
_initialize_i386_darwin_nat (void)
{
#ifdef BFD64
amd64_native_gregset64_reg_offset = amd64_darwin_thread_state_reg_offset;
@ -637,8 +646,6 @@ darwin_complete_target (struct target_ops *target)
amd64_native_gregset32_num_regs = i386_darwin_thread_state_num_regs;
#endif
x86_use_watchpoints (target);
x86_dr_low.set_control = i386_darwin_dr_set_control;
x86_dr_low.set_addr = i386_darwin_dr_set_addr;
x86_dr_low.get_addr = i386_darwin_dr_get_addr;
@ -652,6 +659,5 @@ darwin_complete_target (struct target_ops *target)
x86_set_debug_register_length (4);
#endif
target->to_fetch_registers = i386_darwin_fetch_inferior_registers;
target->to_store_registers = i386_darwin_store_inferior_registers;
add_target (&darwin_target);
}

View File

@ -34,12 +34,29 @@
#include "x86-bsd-nat.h"
#include "i386-bsd-nat.h"
class i386_fbsd_nat_target final
: public i386_bsd_nat_target<fbsd_nat_target>
{
public:
/* Add some extra features to the common *BSD/i386 target. */
#ifdef PT_GETXSTATE_INFO
const struct target_desc *read_description () override;
#endif
void resume (ptid_t, int, enum gdb_signal) override;
#if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
int supports_stopped_by_hw_breakpoint () override;
#endif
};
static i386_fbsd_nat_target the_i386_fbsd_nat_target;
/* Resume execution of the inferior process. If STEP is nonzero,
single-step it. If SIGNAL is nonzero, give it that signal. */
static void
i386fbsd_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signal)
void
i386_fbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
{
pid_t pid = ptid_get_pid (ptid);
int request = PT_STEP;
@ -119,10 +136,10 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
#ifdef PT_GETXSTATE_INFO
/* Implement the to_read_description method. */
/* Implement the read_description method. */
static const struct target_desc *
i386fbsd_read_description (struct target_ops *ops)
const struct target_desc *
i386_fbsd_nat_target::read_description ()
{
static int xsave_probed;
static uint64_t xcr0;
@ -147,20 +164,20 @@ i386fbsd_read_description (struct target_ops *ops)
}
#endif
#if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
/* Implement the supports_stopped_by_hw_breakpoints method. */
int
i386_fbsd_nat_target::supports_stopped_by_hw_breakpoint ()
{
return 1;
}
#endif
void
_initialize_i386fbsd_nat (void)
{
struct target_ops *t;
/* Add some extra features to the common *BSD/i386 target. */
t = i386bsd_target ();
#ifdef PT_GETXSTATE_INFO
t->to_read_description = i386fbsd_read_description;
#endif
t->to_resume = i386fbsd_resume;
fbsd_nat_add_target (t);
add_target (&the_i386_fbsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (i386fbsd_supply_pcb);

View File

@ -54,6 +54,23 @@ static int reg_offset[] =
#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
/* The i386 GNU Hurd target. */
#ifdef i386_DEBUG_STATE
using gnu_base_target = x86_nat_target<gnu_nat_target>;
#else
using gnu_base_target = gnu_nat_target;
#endif
struct i386_gnu_nat_target final : public gnu_base_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static i386_gnu_nat_target the_i386_gnu_nat_target;
/* Get the whole floating-point state of THREAD and record the values
of the corresponding (pseudo) registers. */
@ -412,14 +429,7 @@ i386_gnu_dr_get_control (void)
void
_initialize_i386gnu_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Hurd methods. */
t = gnu_target ();
#ifdef i386_DEBUG_STATE
x86_use_watchpoints (t);
x86_dr_low.set_control = i386_gnu_dr_set_control;
gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
x86_dr_low.set_addr = i386_gnu_dr_set_addr;
@ -429,9 +439,6 @@ _initialize_i386gnu_nat (void)
x86_set_debug_register_length (4);
#endif /* i386_DEBUG_STATE */
t->to_fetch_registers = gnu_fetch_registers;
t->to_store_registers = gnu_store_registers;
/* Register the target. */
add_target (t);
add_target (&the_i386_gnu_nat_target);
}

View File

@ -33,11 +33,22 @@
#include "i386-linux-tdep.h"
#include "x86-xstate.h"
#include "linux-nat.h"
#include "x86-linux-nat.h"
#include "nat/linux-ptrace.h"
#include "inf-ptrace.h"
struct i386_linux_nat_target final : public x86_linux_nat_target
{
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
/* Override the default ptrace resume method. */
void low_resume (ptid_t ptid, int step, enum gdb_signal sig) override;
};
static i386_linux_nat_target the_i386_linux_nat_target;
/* The register sets used in GNU/Linux ELF core-dumps are identical to
the register sets in `struct user' that is used for a.out
core-dumps, and is also used by `ptrace'. The corresponding types
@ -446,9 +457,8 @@ store_fpxregs (const struct regcache *regcache, int tid, int regno)
this for all registers (including the floating point and SSE
registers). */
static void
i386_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
i386_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
pid_t tid;
@ -478,7 +488,7 @@ i386_linux_fetch_inferior_registers (struct target_ops *ops,
/* The call above might reset `have_ptrace_getregs'. */
if (!have_ptrace_getregs)
{
i386_linux_fetch_inferior_registers (ops, regcache, regno);
fetch_registers (regcache, regno);
return;
}
@ -524,9 +534,8 @@ i386_linux_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating point and SSE
registers). */
static void
i386_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
i386_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
pid_t tid;
@ -635,9 +644,8 @@ static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
static void
i386_linux_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signal)
void
i386_linux_nat_target::low_resume (ptid_t ptid, int step, enum gdb_signal signal)
{
int pid = ptid_get_lwp (ptid);
int request;
@ -706,16 +714,8 @@ i386_linux_resume (struct target_ops *ops,
void
_initialize_i386_linux_nat (void)
{
/* Create a generic x86 GNU/Linux target. */
struct target_ops *t = x86_linux_create_target ();
/* Override the default ptrace resume method. */
t->to_resume = i386_linux_resume;
/* Add our register access methods. */
t->to_fetch_registers = i386_linux_fetch_inferior_registers;
t->to_store_registers = i386_linux_store_inferior_registers;
linux_target = &the_i386_linux_nat_target;
/* Add the target. */
x86_linux_add_target (t);
x86_linux_add_target (linux_target);
}

View File

@ -71,16 +71,13 @@ i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
static i386_bsd_nat_target<nbsd_nat_target> the_i386_nbsd_nat_target;
void
_initialize_i386nbsd_nat (void)
{
struct target_ops *t;
add_target (&the_i386_nbsd_nat_target);
/* Add some extra features to the common *BSD/i386 target. */
t = i386bsd_target ();
t->to_pid_to_exec_file = nbsd_pid_to_exec_file;
add_target (t);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (i386nbsd_supply_pcb);
}

View File

@ -88,11 +88,12 @@ i386obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
return 1;
}
static i386_bsd_nat_target<obsd_nat_target> the_i386_obsd_nat_target;
void
_initialize_i386obsd_nat (void)
{
/* Add some extra features to the common *BSD/i386 target. */
obsd_add_target (i386bsd_target ());
add_target (&i386_obsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (i386obsd_supply_pcb);

View File

@ -43,6 +43,46 @@
#include "inf-ptrace.h"
class ia64_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
const struct target_desc *read_description () override;
/* Override watchpoint routines. */
/* The IA-64 architecture can step over a watch point (without
triggering it again) if the "dd" (data debug fault disable) bit
in the processor status word is set.
This PSR bit is set in
ia64_linux_nat_target::stopped_by_watchpoint when the code there
has determined that a hardware watchpoint has indeed been hit.
The CPU will then be able to execute one instruction without
triggering a watchpoint. */
int have_steppable_watchpoint () { return 1; }
int can_use_hw_breakpoint (enum bptype, int, int) override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
};
static ia64_linux_nat_target the_ia64_linux_nat_target;
/* These must match the order of the register names.
Some sort of lookup table is needed because the offsets associated
@ -542,11 +582,10 @@ is_power_of_2 (int val)
return onecount <= 1;
}
static int
ia64_linux_insert_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
ia64_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
struct lwp_info *lp;
int idx;
@ -598,11 +637,10 @@ ia64_linux_insert_watchpoint (struct target_ops *self,
return 0;
}
static int
ia64_linux_remove_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
ia64_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
int idx;
long dbr_addr, dbr_mask;
@ -650,8 +688,8 @@ ia64_linux_new_thread (struct lwp_info *lp)
enable_watchpoints_in_psr (lp->ptid);
}
static int
ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
int
ia64_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
{
CORE_ADDR psr;
siginfo_t siginfo;
@ -673,11 +711,11 @@ ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
return 1;
}
static int
ia64_linux_stopped_by_watchpoint (struct target_ops *ops)
int
ia64_linux_nat_target::stopped_by_watchpoint ()
{
CORE_ADDR addr;
return ia64_linux_stopped_data_address (ops, &addr);
return stopped_data_address (&addr);
}
static int
@ -765,9 +803,8 @@ ia64_linux_fetch_register (struct regcache *regcache, int regnum)
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
ia64_linux_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ia64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
if (regnum == -1)
for (regnum = 0;
@ -820,9 +857,8 @@ ia64_linux_store_register (const struct regcache *regcache, int regnum)
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
static void
ia64_linux_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ia64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
{
if (regnum == -1)
for (regnum = 0;
@ -833,18 +869,14 @@ ia64_linux_store_registers (struct target_ops *ops,
ia64_linux_store_register (regcache, regnum);
}
/* Implement the xfer_partial target_ops method. */
static target_xfer_partial_ftype *super_xfer_partial;
/* Implement the to_xfer_partial target_ops method. */
static enum target_xfer_status
ia64_linux_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
enum target_xfer_status
ia64_linux_nat_target::xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_UNWIND_TABLE && readbuf != NULL)
{
@ -875,8 +907,8 @@ ia64_linux_xfer_partial (struct target_ops *ops,
return TARGET_XFER_OK;
}
return super_xfer_partial (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
return linux_nat_target::xfer_partial (object, annex, readbuf, writebuf,
offset, len, xfered_len);
}
/* For break.b instruction ia64 CPU forgets the immediate value and generates
@ -894,39 +926,11 @@ ia64_linux_status_is_event (int status)
void
_initialize_ia64_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Override the default fetch/store register routines. */
t->to_fetch_registers = ia64_linux_fetch_registers;
t->to_store_registers = ia64_linux_store_registers;
/* Override the default to_xfer_partial. */
super_xfer_partial = t->to_xfer_partial;
t->to_xfer_partial = ia64_linux_xfer_partial;
/* Override watchpoint routines. */
/* The IA-64 architecture can step over a watch point (without triggering
it again) if the "dd" (data debug fault disable) bit in the processor
status word is set.
This PSR bit is set in ia64_linux_stopped_by_watchpoint when the
code there has determined that a hardware watchpoint has indeed
been hit. The CPU will then be able to execute one instruction
without triggering a watchpoint. */
t->to_have_steppable_watchpoint = 1;
t->to_can_use_hw_breakpoint = ia64_linux_can_use_hw_breakpoint;
t->to_stopped_by_watchpoint = ia64_linux_stopped_by_watchpoint;
t->to_stopped_data_address = ia64_linux_stopped_data_address;
t->to_insert_watchpoint = ia64_linux_insert_watchpoint;
t->to_remove_watchpoint = ia64_linux_remove_watchpoint;
struct target_ops *t = &the_ia64_linux_nat_target;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_ia64_linux_nat_target;
add_target (t);
linux_nat_set_new_thread (t, ia64_linux_new_thread);
linux_nat_set_status_is_event (t, ia64_linux_status_is_event);
}

View File

@ -2660,7 +2660,7 @@ getunwind_table (gdb_byte **buf_p)
we should find a way to override the corefile layer's
xfer_partial method. */
x = target_read_alloc (&current_target, TARGET_OBJECT_UNWIND_TABLE,
x = target_read_alloc (target_stack, TARGET_OBJECT_UNWIND_TABLE,
NULL, buf_p);
return x;

View File

@ -42,7 +42,7 @@ ia64_vms_find_proc_info_x (unw_addr_space_t as, unw_word_t ip,
CORE_ADDR table_addr;
unsigned int info_len;
res = target_read (&current_target, TARGET_OBJECT_OPENVMS_UIB,
res = target_read (target_stack, TARGET_OBJECT_OPENVMS_UIB,
annex + 2, buf, 0, sizeof (buf));
if (res != sizeof (buf))

View File

@ -39,11 +39,6 @@
#include <fcntl.h>
#include <unistd.h>
/* A pointer to what is returned by inf_child_target. Used by
inf_child_open to push the most-derived target in reaction to
"target native". */
static struct target_ops *inf_child_ops = NULL;
/* Helper function for child_wait and the derivatives of child_wait.
HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
translation of that in OURSTATUS. */
@ -67,35 +62,11 @@ store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus)
}
}
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
inf_child_target::~inf_child_target ()
{}
static void
inf_child_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
{
if (regnum == -1)
{
for (regnum = 0;
regnum < gdbarch_num_regs (regcache->arch ());
regnum++)
regcache_raw_supply (regcache, regnum, NULL);
}
else
regcache_raw_supply (regcache, regnum, NULL);
}
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating point registers). */
static void
inf_child_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
{
}
static void
inf_child_post_attach (struct target_ops *self, int pid)
void
inf_child_target::post_attach (int pid)
{
/* This target doesn't require a meaningful "post attach" operation
by a debugger. */
@ -107,12 +78,59 @@ inf_child_post_attach (struct target_ops *self, int pid)
makes sure that registers contains all the registers from the
program being debugged. */
static void
inf_child_prepare_to_store (struct target_ops *self,
struct regcache *regcache)
void
inf_child_target::prepare_to_store (struct regcache *regcache)
{
}
bool
inf_child_target::supports_terminal_ours ()
{
return true;
}
void
inf_child_target::terminal_init ()
{
child_terminal_init (this);
}
void
inf_child_target::terminal_inferior ()
{
child_terminal_inferior (this);
}
void
inf_child_target::terminal_ours_for_output ()
{
child_terminal_ours_for_output (this);
}
void
inf_child_target::terminal_ours ()
{
child_terminal_ours (this);
}
void
inf_child_target::interrupt ()
{
child_interrupt (this);
}
void
inf_child_target::pass_ctrlc ()
{
child_pass_ctrlc (this);
}
void
inf_child_target::terminal_info (const char *args, int from_tty)
{
child_terminal_info (this, args, from_tty);
}
/* True if the user did "target native". In that case, we won't
unpush the child target automatically when the last inferior is
gone. */
@ -131,16 +149,16 @@ inf_child_open_target (struct target_ops *target, const char *arg,
printf_filtered ("Done. Use the \"run\" command to start a process.\n");
}
static void
inf_child_open (const char *arg, int from_tty)
void
inf_child_target::open (const char *arg, int from_tty)
{
inf_child_open_target (inf_child_ops, arg, from_tty);
inf_child_open_target (this, arg, from_tty);
}
/* Implement the to_disconnect target_ops method. */
static void
inf_child_disconnect (struct target_ops *target, const char *args, int from_tty)
void
inf_child_target::disconnect (const char *args, int from_tty)
{
if (args != NULL)
error (_("Argument given to \"disconnect\"."));
@ -152,65 +170,98 @@ inf_child_disconnect (struct target_ops *target, const char *args, int from_tty)
/* Implement the to_close target_ops method. */
static void
inf_child_close (struct target_ops *target)
void
inf_child_target::close ()
{
/* In case we were forcibly closed. */
inf_child_explicitly_opened = 0;
}
void
inf_child_mourn_inferior (struct target_ops *ops)
inf_child_target::mourn_inferior ()
{
generic_mourn_inferior ();
inf_child_maybe_unpush_target (ops);
maybe_unpush_target ();
}
/* See inf-child.h. */
void
inf_child_maybe_unpush_target (struct target_ops *ops)
inf_child_target::maybe_unpush_target ()
{
if (!inf_child_explicitly_opened && !have_inferiors ())
unpush_target (ops);
unpush_target (this);
}
static void
inf_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
void
inf_child_target::post_startup_inferior (ptid_t ptid)
{
/* This target doesn't require a meaningful "post startup inferior"
operation by a debugger. */
}
static int
inf_child_follow_fork (struct target_ops *ops, int follow_child,
int detach_fork)
{
/* This target doesn't support following fork or vfork events. */
return 0;
}
static int
inf_child_can_run (struct target_ops *self)
int
inf_child_target::can_run ()
{
return 1;
}
static char *
inf_child_pid_to_exec_file (struct target_ops *self, int pid)
bool
inf_child_target::can_create_inferior ()
{
return true;
}
bool
inf_child_target::can_attach ()
{
return true;
}
char *
inf_child_target::pid_to_exec_file (int pid)
{
/* This target doesn't support translation of a process ID to the
filename of the executable file. */
return NULL;
}
int
inf_child_target::has_all_memory ()
{
return default_child_has_all_memory ();
}
int
inf_child_target::has_memory ()
{
return default_child_has_memory ();
}
int
inf_child_target::has_stack ()
{
return default_child_has_stack ();
}
int
inf_child_target::has_registers ()
{
return default_child_has_registers ();
}
int
inf_child_target::has_execution (ptid_t ptid)
{
return default_child_has_execution (ptid);
}
/* Implementation of to_fileio_open. */
static int
inf_child_fileio_open (struct target_ops *self,
struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno)
int
inf_child_target::fileio_open (struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno)
{
int nat_flags;
mode_t nat_mode;
@ -232,10 +283,9 @@ inf_child_fileio_open (struct target_ops *self,
/* Implementation of to_fileio_pwrite. */
static int
inf_child_fileio_pwrite (struct target_ops *self,
int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno)
int
inf_child_target::fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno)
{
int ret;
@ -260,10 +310,9 @@ inf_child_fileio_pwrite (struct target_ops *self,
/* Implementation of to_fileio_pread. */
static int
inf_child_fileio_pread (struct target_ops *self,
int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno)
int
inf_child_target::fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno)
{
int ret;
@ -288,9 +337,8 @@ inf_child_fileio_pread (struct target_ops *self,
/* Implementation of to_fileio_fstat. */
static int
inf_child_fileio_fstat (struct target_ops *self, int fd,
struct stat *sb, int *target_errno)
int
inf_child_target::fileio_fstat (int fd, struct stat *sb, int *target_errno)
{
int ret;
@ -303,12 +351,12 @@ inf_child_fileio_fstat (struct target_ops *self, int fd,
/* Implementation of to_fileio_close. */
static int
inf_child_fileio_close (struct target_ops *self, int fd, int *target_errno)
int
inf_child_target::fileio_close (int fd, int *target_errno)
{
int ret;
ret = close (fd);
ret = ::close (fd);
if (ret == -1)
*target_errno = host_to_fileio_error (errno);
@ -317,10 +365,9 @@ inf_child_fileio_close (struct target_ops *self, int fd, int *target_errno)
/* Implementation of to_fileio_unlink. */
static int
inf_child_fileio_unlink (struct target_ops *self,
struct inferior *inf, const char *filename,
int *target_errno)
int
inf_child_target::fileio_unlink (struct inferior *inf, const char *filename,
int *target_errno)
{
int ret;
@ -333,10 +380,9 @@ inf_child_fileio_unlink (struct target_ops *self,
/* Implementation of to_fileio_readlink. */
static gdb::optional<std::string>
inf_child_fileio_readlink (struct target_ops *self,
struct inferior *inf, const char *filename,
int *target_errno)
gdb::optional<std::string>
inf_child_target::fileio_readlink (struct inferior *inf, const char *filename,
int *target_errno)
{
/* We support readlink only on systems that also provide a compile-time
maximum path length (PATH_MAX), at least for now. */
@ -358,86 +404,25 @@ inf_child_fileio_readlink (struct target_ops *self,
#endif
}
static int
inf_child_use_agent (struct target_ops *self, int use)
int
inf_child_target::use_agent (int use)
{
if (agent_loaded_p ())
{
use_agent = use;
::use_agent = use;
return 1;
}
else
return 0;
}
static int
inf_child_can_use_agent (struct target_ops *self)
int
inf_child_target::can_use_agent ()
{
return agent_loaded_p ();
}
/* Default implementation of the to_can_async_p and
to_supports_non_stop methods. */
static int
return_zero (struct target_ops *ignore)
inf_child_target::inf_child_target ()
{
return 0;
}
struct target_ops *
inf_child_target (void)
{
struct target_ops *t = XCNEW (struct target_ops);
t->to_shortname = "native";
t->to_longname = "Native process";
t->to_doc = "Native process (started by the \"run\" command).";
t->to_open = inf_child_open;
t->to_close = inf_child_close;
t->to_disconnect = inf_child_disconnect;
t->to_post_attach = inf_child_post_attach;
t->to_fetch_registers = inf_child_fetch_inferior_registers;
t->to_store_registers = inf_child_store_inferior_registers;
t->to_prepare_to_store = inf_child_prepare_to_store;
t->to_insert_breakpoint = memory_insert_breakpoint;
t->to_remove_breakpoint = memory_remove_breakpoint;
t->to_terminal_init = child_terminal_init;
t->to_terminal_inferior = child_terminal_inferior;
t->to_terminal_save_inferior = child_terminal_save_inferior;
t->to_terminal_ours_for_output = child_terminal_ours_for_output;
t->to_terminal_ours = child_terminal_ours;
t->to_terminal_info = child_terminal_info;
t->to_pass_ctrlc = child_pass_ctrlc;
t->to_interrupt = child_interrupt;
t->to_post_startup_inferior = inf_child_post_startup_inferior;
t->to_follow_fork = inf_child_follow_fork;
t->to_can_run = inf_child_can_run;
/* We must default these because they must be implemented by any
target that can run. */
t->to_can_async_p = return_zero;
t->to_supports_non_stop = return_zero;
t->to_pid_to_exec_file = inf_child_pid_to_exec_file;
t->to_stratum = process_stratum;
t->to_has_all_memory = default_child_has_all_memory;
t->to_has_memory = default_child_has_memory;
t->to_has_stack = default_child_has_stack;
t->to_has_registers = default_child_has_registers;
t->to_has_execution = default_child_has_execution;
t->to_fileio_open = inf_child_fileio_open;
t->to_fileio_pwrite = inf_child_fileio_pwrite;
t->to_fileio_pread = inf_child_fileio_pread;
t->to_fileio_fstat = inf_child_fileio_fstat;
t->to_fileio_close = inf_child_fileio_close;
t->to_fileio_unlink = inf_child_fileio_unlink;
t->to_fileio_readlink = inf_child_fileio_readlink;
t->to_magic = OPS_MAGIC;
t->to_use_agent = inf_child_use_agent;
t->to_can_use_agent = inf_child_can_use_agent;
/* Store a pointer so we can push the most-derived target from
inf_child_open. */
inf_child_ops = t;
return t;
this->to_stratum = process_stratum;
}

View File

@ -20,33 +20,108 @@
#ifndef INF_CHILD_H
#define INF_CHILD_H
/* Create a prototype child target. The client can override it with
local methods. */
#include "target.h"
extern struct target_ops *inf_child_target (void);
/* A prototype child target. The client can override it with local
methods. */
class inf_child_target
: public memory_breakpoint_target<target_ops>
{
public:
inf_child_target ();
~inf_child_target () override = 0;
const char *shortname () override
{ return "native"; }
const char *longname () override
{ return _("Native process"); }
const char *doc () override
{ return _("Native process (started by the \"run\" command)."); }
void open (const char *arg, int from_tty) override;
void close () override;
void disconnect (const char *, int) override;
void fetch_registers (struct regcache *, int) override = 0;
void store_registers (struct regcache *, int) override = 0;
void prepare_to_store (struct regcache *) override;
bool supports_terminal_ours () override;
void terminal_init () override;
void terminal_inferior () override;
void terminal_ours_for_output () override;
void terminal_ours () override;
void terminal_info (const char *, int) override;
void interrupt () override;
void pass_ctrlc () override;
void post_startup_inferior (ptid_t) override;
void mourn_inferior () override;
int can_run () override;
bool can_create_inferior () override;
void create_inferior (const char *, const std::string &,
char **, int) override = 0;
bool can_attach () override;
void attach (const char *, int) override = 0;
void post_attach (int) override;
/* We must default these because they must be implemented by any
target that can run. */
int can_async_p () override { return 0; }
int supports_non_stop () override { return 0; }
int supports_disable_randomization () override { return 0; }
char *pid_to_exec_file (int pid) override;
int has_all_memory () override;
int has_memory () override;
int has_stack () override;
int has_registers () override;
int has_execution (ptid_t) override;
int fileio_open (struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno) override;
int fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno) override;
int fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno) override;
int fileio_fstat (int fd, struct stat *sb, int *target_errno) override;
int fileio_close (int fd, int *target_errno) override;
int fileio_unlink (struct inferior *inf,
const char *filename,
int *target_errno) override;
gdb::optional<std::string> fileio_readlink (struct inferior *inf,
const char *filename,
int *target_errno) override;
int use_agent (int use) override;
int can_use_agent () override;
protected:
/* Unpush the target if it wasn't explicitly open with "target native"
and there are no live inferiors left. Note: if calling this as a
result of a mourn or detach, the current inferior shall already
have its PID cleared, so it isn't counted as live. That's usually
done by calling either generic_mourn_inferior or
detach_inferior. */
void maybe_unpush_target ();
};
/* Functions for helping to write a native target. */
/* This is for native targets which use a unix/POSIX-style waitstatus. */
extern void store_waitstatus (struct target_waitstatus *, int);
/* This is to be called by the native target's open routine to push
the target, in case it need to override to_open. */
extern void inf_child_open_target (struct target_ops *target,
const char *arg, int from_tty);
/* To be called by the native target's to_mourn_inferior routine. */
extern void inf_child_mourn_inferior (struct target_ops *ops);
/* Unpush the target if it wasn't explicitly open with "target native"
and there are no live inferiors left. Note: if calling this as a
result of a mourn or detach, the current inferior shall already
have its PID cleared, so it isn't counted as live. That's usually
done by calling either generic_mourn_inferior or
detach_inferior. */
extern void inf_child_maybe_unpush_target (struct target_ops *ops);
#endif

View File

@ -52,14 +52,16 @@ typedef std::unique_ptr<struct target_ops, target_unpusher> target_unpush_up;
inf_ptrace_target::~inf_ptrace_target ()
{}
#ifdef PT_GET_PROCESS_STATE
/* Target hook for follow_fork. On entry and at return inferior_ptid is
the ptid of the followed inferior. */
static int
inf_ptrace_follow_fork (struct target_ops *ops, int follow_child,
int detach_fork)
int
inf_ptrace_target::follow_fork (int follow_child, int detach_fork)
{
if (!follow_child)
{
@ -76,14 +78,14 @@ inf_ptrace_follow_fork (struct target_ops *ops, int follow_child,
return 0;
}
static int
inf_ptrace_insert_fork_catchpoint (struct target_ops *self, int pid)
int
inf_ptrace_target::insert_fork_catchpoint (int pid)
{
return 0;
}
static int
inf_ptrace_remove_fork_catchpoint (struct target_ops *self, int pid)
int
inf_ptrace_target::remove_fork_catchpoint (int pid)
{
return 0;
}
@ -106,24 +108,24 @@ inf_ptrace_me (void)
ENV is the environment vector to pass. If FROM_TTY is non-zero, be
chatty about it. */
static void
inf_ptrace_create_inferior (struct target_ops *ops,
const char *exec_file, const std::string &allargs,
char **env, int from_tty)
void
inf_ptrace_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
pid_t pid;
ptid_t ptid;
/* Do not change either targets above or the same target if already present.
The reason is the target stack is shared across multiple inferiors. */
int ops_already_pushed = target_is_pushed (ops);
int ops_already_pushed = target_is_pushed (this);
target_unpush_up unpusher;
if (! ops_already_pushed)
{
/* Clear possible core file with its process_stratum. */
push_target (ops);
unpusher.reset (ops);
push_target (this);
unpusher.reset (this);
}
pid = fork_inferior (exec_file, allargs, env, inf_ptrace_me, NULL,
@ -146,8 +148,8 @@ inf_ptrace_create_inferior (struct target_ops *ops,
#ifdef PT_GET_PROCESS_STATE
static void
inf_ptrace_post_startup_inferior (struct target_ops *self, ptid_t pid)
void
inf_ptrace_target::post_startup_inferior (ptid_t pid)
{
ptrace_event_t pe;
@ -163,8 +165,8 @@ inf_ptrace_post_startup_inferior (struct target_ops *self, ptid_t pid)
/* Clean up a rotting corpse of an inferior after it died. */
static void
inf_ptrace_mourn_inferior (struct target_ops *ops)
void
inf_ptrace_target::mourn_inferior ()
{
int status;
@ -174,14 +176,14 @@ inf_ptrace_mourn_inferior (struct target_ops *ops)
only report its exit status to its original parent. */
waitpid (ptid_get_pid (inferior_ptid), &status, 0);
inf_child_mourn_inferior (ops);
inf_child_target::mourn_inferior ();
}
/* Attach to the process specified by ARGS. If FROM_TTY is non-zero,
be chatty about it. */
static void
inf_ptrace_attach (struct target_ops *ops, const char *args, int from_tty)
void
inf_ptrace_target::attach (const char *args, int from_tty)
{
char *exec_file;
pid_t pid;
@ -189,7 +191,7 @@ inf_ptrace_attach (struct target_ops *ops, const char *args, int from_tty)
/* Do not change either targets above or the same target if already present.
The reason is the target stack is shared across multiple inferiors. */
int ops_already_pushed = target_is_pushed (ops);
int ops_already_pushed = target_is_pushed (this);
pid = parse_pid_to_attach (args);
@ -201,8 +203,8 @@ inf_ptrace_attach (struct target_ops *ops, const char *args, int from_tty)
{
/* target_pid_to_str already uses the target. Also clear possible core
file with its process_stratum. */
push_target (ops);
unpusher.reset (ops);
push_target (this);
unpusher.reset (this);
}
if (from_tty)
@ -245,8 +247,8 @@ inf_ptrace_attach (struct target_ops *ops, const char *args, int from_tty)
#ifdef PT_GET_PROCESS_STATE
static void
inf_ptrace_post_attach (struct target_ops *self, int pid)
void
inf_ptrace_target::post_attach (int pid)
{
ptrace_event_t pe;
@ -262,8 +264,8 @@ inf_ptrace_post_attach (struct target_ops *self, int pid)
/* Detach from the inferior. If FROM_TTY is non-zero, be chatty about it. */
static void
inf_ptrace_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
inf_ptrace_target::detach (inferior *inf, int from_tty)
{
pid_t pid = ptid_get_pid (inferior_ptid);
@ -282,24 +284,24 @@ inf_ptrace_detach (struct target_ops *ops, inferior *inf, int from_tty)
error (_("This system does not support detaching from a process"));
#endif
inf_ptrace_detach_success (ops, inf);
detach_success (inf);
}
/* See inf-ptrace.h. */
void
inf_ptrace_detach_success (struct target_ops *ops, inferior *inf)
inf_ptrace_target::detach_success (inferior *inf)
{
inferior_ptid = null_ptid;
detach_inferior (inf);
inf_child_maybe_unpush_target (ops);
maybe_unpush_target ();
}
/* Kill the inferior. */
static void
inf_ptrace_kill (struct target_ops *ops)
void
inf_ptrace_target::kill ()
{
pid_t pid = ptid_get_pid (inferior_ptid);
int status;
@ -333,9 +335,8 @@ get_ptrace_pid (ptid_t ptid)
STEP is nonzero, single-step it. If SIGNAL is nonzero, give it
that signal. */
static void
inf_ptrace_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signal)
void
inf_ptrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
{
pid_t pid;
int request;
@ -375,9 +376,9 @@ inf_ptrace_resume (struct target_ops *ops,
process ID of the child, or MINUS_ONE_PTID in case of error; store
the status in *OURSTATUS. */
static ptid_t
inf_ptrace_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus, int options)
ptid_t
inf_ptrace_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int options)
{
pid_t pid;
int status, save_errno;
@ -523,11 +524,11 @@ inf_ptrace_peek_poke (pid_t pid, gdb_byte *readbuf,
/* Implement the to_xfer_partial target_ops method. */
static enum target_xfer_status
inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
inf_ptrace_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
pid_t pid = get_ptrace_pid (inferior_ptid);
@ -609,17 +610,17 @@ inf_ptrace_xfer_partial (struct target_ops *ops, enum target_object object,
/* Return non-zero if the thread specified by PTID is alive. */
static int
inf_ptrace_thread_alive (struct target_ops *ops, ptid_t ptid)
int
inf_ptrace_target::thread_alive (ptid_t ptid)
{
/* ??? Is kill the right way to do this? */
return (kill (ptid_get_pid (ptid), 0) != -1);
return (::kill (ptid_get_pid (ptid), 0) != -1);
}
/* Print status information about what we're accessing. */
static void
inf_ptrace_files_info (struct target_ops *ignore)
void
inf_ptrace_target::files_info ()
{
struct inferior *inf = current_inferior ();
@ -628,8 +629,8 @@ inf_ptrace_files_info (struct target_ops *ignore)
target_pid_to_str (inferior_ptid));
}
static const char *
inf_ptrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
inf_ptrace_target::pid_to_str (ptid_t ptid)
{
return normal_pid_to_str (ptid);
}
@ -641,9 +642,9 @@ inf_ptrace_pid_to_str (struct target_ops *ops, ptid_t ptid)
Return -1 if there is insufficient buffer for a whole entry.
Return 1 if an entry was read into *TYPEP and *VALP. */
static int
inf_ptrace_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
int
inf_ptrace_target::auxv_parse (gdb_byte **readptr, gdb_byte *endptr,
CORE_ADDR *typep, CORE_ADDR *valp)
{
struct type *int_type = builtin_type (target_gdbarch ())->builtin_int;
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
@ -668,37 +669,4 @@ inf_ptrace_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
}
#endif
/* Create a prototype ptrace target. The client can override it with
local methods. */
struct target_ops *
inf_ptrace_target (void)
{
struct target_ops *t = inf_child_target ();
t->to_attach = inf_ptrace_attach;
t->to_detach = inf_ptrace_detach;
t->to_resume = inf_ptrace_resume;
t->to_wait = inf_ptrace_wait;
t->to_files_info = inf_ptrace_files_info;
t->to_kill = inf_ptrace_kill;
t->to_create_inferior = inf_ptrace_create_inferior;
#ifdef PT_GET_PROCESS_STATE
t->to_follow_fork = inf_ptrace_follow_fork;
t->to_insert_fork_catchpoint = inf_ptrace_insert_fork_catchpoint;
t->to_remove_fork_catchpoint = inf_ptrace_remove_fork_catchpoint;
t->to_post_startup_inferior = inf_ptrace_post_startup_inferior;
t->to_post_attach = inf_ptrace_post_attach;
#endif
t->to_mourn_inferior = inf_ptrace_mourn_inferior;
t->to_thread_alive = inf_ptrace_thread_alive;
t->to_pid_to_str = inf_ptrace_pid_to_str;
t->to_xfer_partial = inf_ptrace_xfer_partial;
#if defined (PT_IO) && defined (PIOD_READ_AUXV)
t->to_auxv_parse = inf_ptrace_auxv_parse;
#endif
return t;
}

View File

@ -20,26 +20,67 @@
#ifndef INF_PTRACE_H
#define INF_PTRACE_H
/* Create a prototype ptrace target. The client can override it with
local methods. */
#include "inf-child.h"
extern struct target_ops *inf_ptrace_target (void);
/* An abstract prototype ptrace target. The client can override it
with local methods. */
/* Create a "traditional" ptrace target. REGISTER_U_OFFSET should be
a function returning the offset within the user area where a
particular register is stored. */
struct inf_ptrace_target : public inf_child_target
{
~inf_ptrace_target () override = 0;
extern struct target_ops *
inf_ptrace_trad_target (CORE_ADDR (*register_u_offset)
(struct gdbarch *, int, int));
void attach (const char *, int) override;
void detach (inferior *inf, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void files_info () override;
void kill () override;
void create_inferior (const char *, const std::string &,
char **, int) override;
#ifdef PT_GET_PROCESS_STATE
int follow_fork (int, int) override;
int insert_fork_catchpoint (int) override;
int remove_fork_catchpoint (int) override;
void post_startup_inferior (ptid_t) override;
void post_attach (int) override;
#endif
void mourn_inferior () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
#if defined (PT_IO) && defined (PIOD_READ_AUXV)
int auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) override;
#endif
protected:
/* Cleanup the inferior after a successful ptrace detach. */
void detach_success (inferior *inf);
};
/* Return which PID to pass to ptrace in order to observe/control the
tracee identified by PTID. */
extern pid_t get_ptrace_pid (ptid_t);
/* Cleanup the inferior after a successful ptrace detach. */
extern void inf_ptrace_detach_success (struct target_ops *ops, inferior *inf);
#endif

View File

@ -256,7 +256,7 @@ find_function_addr (struct value *function,
if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
|| TYPE_CODE (ftype) == TYPE_CODE_METHOD)
funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
&current_target);
target_stack);
}
if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
|| TYPE_CODE (ftype) == TYPE_CODE_METHOD)
@ -308,7 +308,7 @@ find_function_addr (struct value *function,
funaddr = value_as_address (value_addr (function));
nfunaddr = funaddr;
funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
&current_target);
target_stack);
if (funaddr != nfunaddr)
found_descriptor = 1;
}

View File

@ -531,7 +531,7 @@ prepare_execution_command (struct target_ops *target, int background)
{
/* If we get a request for running in the bg but the target
doesn't support it, error out. */
if (background && !target->to_can_async_p (target))
if (background && !target->can_async_p ())
error (_("Asynchronous execution not supported on this target."));
if (!background)
@ -600,7 +600,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
prepare_execution_command (run_target, async_exec);
if (non_stop && !run_target->to_supports_non_stop (run_target))
if (non_stop && !run_target->supports_non_stop ())
error (_("The target does not support running in non-stop mode."));
/* Done. Can now set breakpoints, change inferior args, etc. */
@ -639,10 +639,10 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
/* We call get_inferior_args() because we might need to compute
the value now. */
run_target->to_create_inferior (run_target, exec_file,
std::string (get_inferior_args ()),
current_inferior ()->environment.envp (),
from_tty);
run_target->create_inferior (exec_file,
std::string (get_inferior_args ()),
current_inferior ()->environment.envp (),
from_tty);
/* to_create_inferior should push the target, so after this point we
shouldn't refer to run_target again. */
run_target = NULL;
@ -660,7 +660,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
/* Pass zero for FROM_TTY, because at this point the "run" command
has done its thing; now we are setting up the running program. */
post_create_inferior (&current_target, 0);
post_create_inferior (target_stack, 0);
/* Queue a pending event so that the program stops immediately. */
if (run_how == RUN_STOP_AT_FIRST_INSN)
@ -896,7 +896,7 @@ continue_command (const char *args, int from_tty)
ensure_not_running ();
}
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
if (from_tty)
printf_filtered (_("Continuing.\n"));
@ -1043,7 +1043,7 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string)
= strip_bg_char (count_string, &async_exec);
count_string = stripped.get ();
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
count = count_string ? parse_and_eval_long (count_string) : 1;
@ -1232,7 +1232,7 @@ jump_command (const char *arg, int from_tty)
gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
arg = stripped.get ();
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
if (!arg)
error_no_arg (_("starting address"));
@ -1312,7 +1312,7 @@ signal_command (const char *signum_exp, int from_tty)
= strip_bg_char (signum_exp, &async_exec);
signum_exp = stripped.get ();
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
if (!signum_exp)
error_no_arg (_("signal number"));
@ -1585,7 +1585,7 @@ until_command (const char *arg, int from_tty)
gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
arg = stripped.get ();
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
if (arg)
until_break_command (arg, from_tty, 0);
@ -1610,7 +1610,7 @@ advance_command (const char *arg, int from_tty)
gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
arg = stripped.get ();
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
until_break_command (arg, from_tty, 1);
}
@ -1990,7 +1990,7 @@ finish_command (const char *arg, int from_tty)
gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
arg = stripped.get ();
prepare_execution_command (&current_target, async_exec);
prepare_execution_command (target_stack, async_exec);
if (arg)
error (_("The \"finish\" command does not take any arguments."));
@ -2686,7 +2686,7 @@ setup_inferior (int from_tty)
/* Take any necessary post-attaching actions for this platform. */
target_post_attach (ptid_get_pid (inferior_ptid));
post_create_inferior (&current_target, from_tty);
post_create_inferior (target_stack, from_tty);
}
/* What to do after the first program stops after attaching. */
@ -2849,10 +2849,10 @@ attach_command (const char *args, int from_tty)
prepare_execution_command (attach_target, async_exec);
if (non_stop && !attach_target->to_supports_non_stop (attach_target))
if (non_stop && !attach_target->supports_non_stop ())
error (_("Cannot attach to this target in non-stop mode"));
attach_target->to_attach (attach_target, args, from_tty);
attach_target->attach (args, from_tty);
/* to_attach should push the target, so after this point we
shouldn't refer to attach_target again. */
attach_target = NULL;
@ -2903,7 +2903,7 @@ attach_command (const char *args, int from_tty)
/* Some system don't generate traps when attaching to inferior.
E.g. Mach 3 or GNU hurd. */
if (!target_attach_no_wait)
if (!target_attach_no_wait ())
{
struct attach_command_continuation_args *a;

View File

@ -3240,7 +3240,7 @@ start_remote (int from_tty)
/* Now that the inferior has stopped, do any bookkeeping like
loading shared libraries. We want to do this before normal_stop,
so that the displayed frame is up to date. */
post_create_inferior (&current_target, from_tty);
post_create_inferior (target_stack, from_tty);
normal_stop ();
}
@ -5697,7 +5697,7 @@ handle_signal_stop (struct execution_control_state *ecs)
fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
if (target_stopped_data_address (&current_target, &addr))
if (target_stopped_data_address (target_stack, &addr))
fprintf_unfiltered (gdb_stdlog,
"infrun: stopped data address = %s\n",
paddress (gdbarch, addr));
@ -8742,7 +8742,7 @@ siginfo_value_read (struct value *v)
validate_registers_access ();
transferred =
target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO,
NULL,
value_contents_all_raw (v),
value_offset (v),
@ -8764,7 +8764,7 @@ siginfo_value_write (struct value *v, struct value *fromval)
vice versa. */
validate_registers_access ();
transferred = target_write (&current_target,
transferred = target_write (target_stack,
TARGET_OBJECT_SIGNAL_INFO,
NULL,
value_contents_all_raw (fromval),
@ -8843,7 +8843,7 @@ save_infcall_suspend_state (void)
siginfo_data = (gdb_byte *) xmalloc (len);
back_to = make_cleanup (xfree, siginfo_data);
if (target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
if (target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
siginfo_data, 0, len) == len)
discard_cleanups (back_to);
else
@ -8893,7 +8893,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
struct type *type = gdbarch_get_siginfo_type (gdbarch);
/* Errors ignored. */
target_write (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
target_write (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
inf_state->siginfo_data, 0, TYPE_LENGTH (type));
}

View File

@ -2303,7 +2303,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
= (gdbarch_convert_from_func_ptr_addr
(gdbarch,
msym_addr,
&current_target));
target_stack));
}
if (msym_addr == addr)

View File

@ -23,14 +23,10 @@
#include "nat/gdb_ptrace.h"
#include "inf-ptrace.h"
/* Pointer to a function that returns the offset within the user area
where a particular register is stored. */
static CORE_ADDR (*inf_ptrace_register_u_offset)(struct gdbarch *, int, int);
/* Fetch register REGNUM from the inferior. */
static void
inf_ptrace_fetch_register (struct regcache *regcache, int regnum)
void
linux_nat_trad_target::fetch_register (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR addr;
@ -40,7 +36,7 @@ inf_ptrace_fetch_register (struct regcache *regcache, int regnum)
int i;
/* This isn't really an address, but ptrace thinks of it as one. */
addr = inf_ptrace_register_u_offset (gdbarch, regnum, 0);
addr = register_u_offset (gdbarch, regnum, 0);
if (addr == (CORE_ADDR)-1
|| gdbarch_cannot_fetch_register (gdbarch, regnum))
{
@ -72,23 +68,23 @@ inf_ptrace_fetch_register (struct regcache *regcache, int regnum)
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
inf_ptrace_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
linux_nat_trad_target::fetch_registers (struct regcache *regcache, int regnum)
{
if (regnum == -1)
for (regnum = 0;
regnum < gdbarch_num_regs (regcache->arch ());
regnum++)
inf_ptrace_fetch_register (regcache, regnum);
fetch_register (regcache, regnum);
else
inf_ptrace_fetch_register (regcache, regnum);
fetch_register (regcache, regnum);
}
/* Store register REGNUM into the inferior. */
static void
inf_ptrace_store_register (const struct regcache *regcache, int regnum)
void
linux_nat_trad_target::store_register (const struct regcache *regcache,
int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
CORE_ADDR addr;
@ -98,7 +94,7 @@ inf_ptrace_store_register (const struct regcache *regcache, int regnum)
int i;
/* This isn't really an address, but ptrace thinks of it as one. */
addr = inf_ptrace_register_u_offset (gdbarch, regnum, 1);
addr = register_u_offset (gdbarch, regnum, 1);
if (addr == (CORE_ADDR)-1
|| gdbarch_cannot_store_register (gdbarch, regnum))
return;
@ -127,34 +123,14 @@ inf_ptrace_store_register (const struct regcache *regcache, int regnum)
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
static void
inf_ptrace_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
linux_nat_trad_target::store_registers (struct regcache *regcache, int regnum)
{
if (regnum == -1)
for (regnum = 0;
regnum < gdbarch_num_regs (regcache->arch ());
regnum++)
inf_ptrace_store_register (regcache, regnum);
store_register (regcache, regnum);
else
inf_ptrace_store_register (regcache, regnum);
}
/* Create a "traditional" Linux/ptrace target. REGISTER_U_OFFSET
should be a function returning the offset within the user area
where a particular register is stored. */
struct target_ops *
linux_trad_target (CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int))
{
struct target_ops *t = inf_ptrace_target();
gdb_assert (register_u_offset);
inf_ptrace_register_u_offset = register_u_offset;
t->to_fetch_registers = inf_ptrace_fetch_registers;
t->to_store_registers = inf_ptrace_store_registers;
linux_target_install_ops (t);
return t;
store_register (regcache, regnum);
}

View File

@ -22,9 +22,25 @@
#include "linux-nat.h"
/* Create a generic GNU/Linux target using traditional
ptrace register access. */
struct target_ops *linux_trad_target
(CORE_ADDR (*register_u_offset)(struct gdbarch *, int, int));
/* A prototype GNU/Linux target using traditional ptrace register
access. A concrete type should override REGISTER_U_OFFSET. */
class linux_nat_trad_target : public linux_nat_target
{
public:
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
protected:
/* Return the offset within the user area where a particular
register is stored. */
virtual CORE_ADDR register_u_offset (struct gdbarch *gdbarch,
int regnum, int store) = 0;
private:
/* Helpers. See definition. */
void fetch_register (struct regcache *regcache, int regnum);
void store_register (const struct regcache *regcache, int regnum);
};
#endif /* LINUX_NAT_TRAD_H */

View File

@ -186,14 +186,11 @@ leader. */
#define O_LARGEFILE 0
#endif
struct linux_nat_target *linux_target;
/* Does the current host support PTRACE_GETREGSET? */
enum tribool have_ptrace_getregset = TRIBOOL_UNKNOWN;
/* The single-threaded native GNU/Linux target_ops. We save a pointer for
the use of the multi-threaded target. */
static struct target_ops *linux_ops;
static struct target_ops linux_ops_saved;
/* The method to call, if any, when a new thread is attached. */
static void (*linux_nat_new_thread) (struct lwp_info *);
@ -217,10 +214,6 @@ static int (*linux_nat_siginfo_fixup) (siginfo_t *,
gdb_byte *,
int);
/* The saved to_xfer_partial method, inherited from inf-ptrace.c.
Called by our to_xfer_partial. */
static target_xfer_partial_ftype *super_xfer_partial;
/* The saved to_close method, inherited from inf-ptrace.c.
Called by our to_close. */
static void (*super_close) (struct target_ops *);
@ -431,14 +424,17 @@ linux_init_ptrace (pid_t pid, int attached)
linux_ptrace_init_warnings ();
}
static void
linux_child_post_attach (struct target_ops *self, int pid)
linux_nat_target::~linux_nat_target ()
{}
void
linux_nat_target::post_attach (int pid)
{
linux_init_ptrace (pid, 1);
}
static void
linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
void
linux_nat_target::post_startup_inferior (ptid_t ptid)
{
linux_init_ptrace (ptid_get_pid (ptid), 0);
}
@ -472,9 +468,8 @@ delete_lwp_cleanup (void *lp_voidp)
ptid of the followed inferior. At return, inferior_ptid will be
unchanged. */
static int
linux_child_follow_fork (struct target_ops *ops, int follow_child,
int detach_fork)
int
linux_nat_target::follow_fork (int follow_child, int detach_fork)
{
if (!follow_child)
{
@ -638,46 +633,45 @@ linux_child_follow_fork (struct target_ops *ops, int follow_child,
}
static int
linux_child_insert_fork_catchpoint (struct target_ops *self, int pid)
int
linux_nat_target::insert_fork_catchpoint (int pid)
{
return !linux_supports_tracefork ();
}
static int
linux_child_remove_fork_catchpoint (struct target_ops *self, int pid)
int
linux_nat_target::remove_fork_catchpoint (int pid)
{
return 0;
}
static int
linux_child_insert_vfork_catchpoint (struct target_ops *self, int pid)
int
linux_nat_target::insert_vfork_catchpoint (int pid)
{
return !linux_supports_tracefork ();
}
static int
linux_child_remove_vfork_catchpoint (struct target_ops *self, int pid)
int
linux_nat_target::remove_vfork_catchpoint (int pid)
{
return 0;
}
static int
linux_child_insert_exec_catchpoint (struct target_ops *self, int pid)
int
linux_nat_target::insert_exec_catchpoint (int pid)
{
return !linux_supports_tracefork ();
}
static int
linux_child_remove_exec_catchpoint (struct target_ops *self, int pid)
int
linux_nat_target::remove_exec_catchpoint (int pid)
{
return 0;
}
static int
linux_child_set_syscall_catchpoint (struct target_ops *self,
int pid, bool needed, int any_count,
gdb::array_view<const int> syscall_counts)
int
linux_nat_target::set_syscall_catchpoint (int pid, bool needed, int any_count,
gdb::array_view<const int> syscall_counts)
{
if (!linux_supports_tracesysgood ())
return 1;
@ -811,9 +805,8 @@ restore_child_signals_mask (sigset_t *prev_mask)
static sigset_t pass_mask;
/* Update signals to pass to the inferior. */
static void
linux_nat_pass_signals (struct target_ops *self,
int numsigs, unsigned char *pass_signals)
void
linux_nat_target::pass_signals (int numsigs, unsigned char *pass_signals)
{
int signo;
@ -831,7 +824,6 @@ linux_nat_pass_signals (struct target_ops *self,
/* Prototypes for local functions. */
static int stop_wait_callback (struct lwp_info *lp, void *data);
static char *linux_child_pid_to_exec_file (struct target_ops *self, int pid);
static int resume_stopped_resumed_lwps (struct lwp_info *lp, void *data);
static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp);
@ -1113,10 +1105,10 @@ linux_nat_post_attach_wait (ptid_t ptid, int *signalled)
return status;
}
static void
linux_nat_create_inferior (struct target_ops *ops,
const char *exec_file, const std::string &allargs,
char **env, int from_tty)
void
linux_nat_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
maybe_disable_address_space_randomization restore_personality
(disable_randomization);
@ -1125,9 +1117,9 @@ linux_nat_create_inferior (struct target_ops *ops,
we have to mask the async mode. */
/* Make sure we report all signals during startup. */
linux_nat_pass_signals (ops, 0, NULL);
pass_signals (0, NULL);
linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty);
inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty);
}
/* Callback for linux_proc_attach_tgid_threads. Attach to PTID if not
@ -1207,19 +1199,19 @@ attach_proc_task_lwp_callback (ptid_t ptid)
return 0;
}
static void
linux_nat_attach (struct target_ops *ops, const char *args, int from_tty)
void
linux_nat_target::attach (const char *args, int from_tty)
{
struct lwp_info *lp;
int status;
ptid_t ptid;
/* Make sure we report all signals during attach. */
linux_nat_pass_signals (ops, 0, NULL);
pass_signals (0, NULL);
TRY
{
linux_ops->to_attach (ops, args, from_tty);
inf_ptrace_target::attach (args, from_tty);
}
CATCH (ex, RETURN_MASK_ERROR)
{
@ -1496,8 +1488,8 @@ detach_callback (struct lwp_info *lp, void *data)
return 0;
}
static void
linux_nat_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
linux_nat_target::detach (inferior *inf, int from_tty)
{
struct lwp_info *main_lwp;
int pid = inf->pid;
@ -1536,7 +1528,7 @@ linux_nat_detach (struct target_ops *ops, inferior *inf, int from_tty)
detach_one_lwp (main_lwp, &signo);
inf_ptrace_detach_success (ops, inf);
detach_success (inf);
}
}
@ -1563,7 +1555,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
if (linux_nat_prepare_to_resume != NULL)
linux_nat_prepare_to_resume (lp);
linux_ops->to_resume (linux_ops, lp->ptid, step, signo);
linux_target->low_resume (lp->ptid, step, signo);
/* Successfully resumed. Clear state that no longer makes sense,
and mark the LWP as running. Must not do this before resuming
@ -1716,9 +1708,8 @@ resume_set_callback (struct lwp_info *lp, void *data)
return 0;
}
static void
linux_nat_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signo)
void
linux_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
{
struct lwp_info *lp;
int resume_many;
@ -2117,7 +2108,7 @@ linux_handle_extended_wait (struct lwp_info *lp, int status)
ourstatus->kind = TARGET_WAITKIND_EXECD;
ourstatus->value.execd_pathname
= xstrdup (linux_child_pid_to_exec_file (NULL, pid));
= xstrdup (linux_proc_pid_to_exec_file (pid));
/* The thread that execed must have been resumed, but, when a
thread execs, it changes its tid to the tgid, and the old
@ -2468,22 +2459,14 @@ maybe_clear_ignore_sigint (struct lwp_info *lp)
static int
check_stopped_by_watchpoint (struct lwp_info *lp)
{
if (linux_ops->to_stopped_by_watchpoint == NULL)
return 0;
scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
inferior_ptid = lp->ptid;
if (linux_ops->to_stopped_by_watchpoint (linux_ops))
if (linux_target->low_stopped_by_watchpoint ())
{
lp->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
if (linux_ops->to_stopped_data_address != NULL)
lp->stopped_data_address_p =
linux_ops->to_stopped_data_address (&current_target,
&lp->stopped_data_address);
else
lp->stopped_data_address_p = 0;
lp->stopped_data_address_p
= linux_target->low_stopped_data_address (&lp->stopped_data_address);
}
return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
@ -2491,8 +2474,8 @@ check_stopped_by_watchpoint (struct lwp_info *lp)
/* Returns true if the LWP had stopped for a watchpoint. */
static int
linux_nat_stopped_by_watchpoint (struct target_ops *ops)
int
linux_nat_target::stopped_by_watchpoint ()
{
struct lwp_info *lp = find_lwp_pid (inferior_ptid);
@ -2501,8 +2484,8 @@ linux_nat_stopped_by_watchpoint (struct target_ops *ops)
return lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
}
static int
linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
int
linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
{
struct lwp_info *lp = find_lwp_pid (inferior_ptid);
@ -2852,8 +2835,8 @@ save_stop_reason (struct lwp_info *lp)
/* Returns true if the LWP had stopped for a software breakpoint. */
static int
linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops)
int
linux_nat_target::stopped_by_sw_breakpoint ()
{
struct lwp_info *lp = find_lwp_pid (inferior_ptid);
@ -2864,8 +2847,8 @@ linux_nat_stopped_by_sw_breakpoint (struct target_ops *ops)
/* Implement the supports_stopped_by_sw_breakpoint method. */
static int
linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
int
linux_nat_target::supports_stopped_by_sw_breakpoint ()
{
return USE_SIGTRAP_SIGINFO;
}
@ -2873,8 +2856,8 @@ linux_nat_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
/* Returns true if the LWP had stopped for a hardware
breakpoint/watchpoint. */
static int
linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops)
int
linux_nat_target::stopped_by_hw_breakpoint ()
{
struct lwp_info *lp = find_lwp_pid (inferior_ptid);
@ -2885,8 +2868,8 @@ linux_nat_stopped_by_hw_breakpoint (struct target_ops *ops)
/* Implement the supports_stopped_by_hw_breakpoint method. */
static int
linux_nat_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
int
linux_nat_target::supports_stopped_by_hw_breakpoint ()
{
return USE_SIGTRAP_SIGINFO;
}
@ -3297,8 +3280,7 @@ filter_exit_event (struct lwp_info *event_child,
}
static ptid_t
linux_nat_wait_1 (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus,
linux_nat_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus,
int target_options)
{
sigset_t prev_mask;
@ -3600,10 +3582,9 @@ resume_stopped_resumed_lwps (struct lwp_info *lp, void *data)
return 0;
}
static ptid_t
linux_nat_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus,
int target_options)
ptid_t
linux_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int target_options)
{
ptid_t event_ptid;
@ -3633,7 +3614,7 @@ linux_nat_wait (struct target_ops *ops,
if (target_is_non_stop_p ())
iterate_over_lwps (minus_one_ptid, resume_stopped_resumed_lwps, &ptid);
event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus, target_options);
event_ptid = linux_nat_wait_1 (ptid, ourstatus, target_options);
/* If we requested any event, and something came out, assume there
may be more. If we requested a specific lwp or process, also
@ -3759,8 +3740,8 @@ kill_unfollowed_fork_children (struct inferior *inf)
}
}
static void
linux_nat_kill (struct target_ops *ops)
void
linux_nat_target::kill ()
{
/* If we're stopped while forking and we haven't followed yet,
kill the other task. We need to do this first because the
@ -3790,8 +3771,8 @@ linux_nat_kill (struct target_ops *ops)
target_mourn_inferior (inferior_ptid);
}
static void
linux_nat_mourn_inferior (struct target_ops *ops)
void
linux_nat_target::mourn_inferior ()
{
int pid = ptid_get_pid (inferior_ptid);
@ -3799,7 +3780,7 @@ linux_nat_mourn_inferior (struct target_ops *ops)
if (! forks_exist_p ())
/* Normal case, no other forks available. */
linux_ops->to_mourn_inferior (ops);
inf_ptrace_target::mourn_inferior ();
else
/* Multi-fork case. The current inferior_ptid has exited, but
there are other viable forks to debug. Delete the exiting
@ -3833,7 +3814,7 @@ siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction)
}
static enum target_xfer_status
linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
linux_xfer_siginfo (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
@ -3888,15 +3869,33 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
}
static enum target_xfer_status
linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
linux_nat_xfer_osdata (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len);
static enum target_xfer_status
linux_proc_xfer_spu (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len);
static enum target_xfer_status
linux_proc_xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, LONGEST len, ULONGEST *xfered_len);
enum target_xfer_status
linux_nat_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
enum target_xfer_status xfer;
if (object == TARGET_OBJECT_SIGNAL_INFO)
return linux_xfer_siginfo (ops, object, annex, readbuf, writebuf,
return linux_xfer_siginfo (object, annex, readbuf, writebuf,
offset, len, xfered_len);
/* The target is connected but no live inferior is selected. Pass
@ -3905,14 +3904,44 @@ linux_nat_xfer_partial (struct target_ops *ops, enum target_object object,
if (object == TARGET_OBJECT_MEMORY && ptid_equal (inferior_ptid, null_ptid))
return TARGET_XFER_EOF;
xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
if (object == TARGET_OBJECT_AUXV)
return memory_xfer_auxv (this, object, annex, readbuf, writebuf,
offset, len, xfered_len);
return xfer;
if (object == TARGET_OBJECT_OSDATA)
return linux_nat_xfer_osdata (object, annex, readbuf, writebuf,
offset, len, xfered_len);
if (object == TARGET_OBJECT_SPU)
return linux_proc_xfer_spu (object, annex, readbuf, writebuf,
offset, len, xfered_len);
/* GDB calculates all addresses in the largest possible address
width.
The address width must be masked before its final use - either by
linux_proc_xfer_partial or inf_ptrace_target::xfer_partial.
Compare ADDR_BIT first to avoid a compiler warning on shift overflow. */
if (object == TARGET_OBJECT_MEMORY)
{
int addr_bit = gdbarch_addr_bit (target_gdbarch ());
if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
offset &= ((ULONGEST) 1 << addr_bit) - 1;
}
xfer = linux_proc_xfer_partial (object, annex, readbuf, writebuf,
offset, len, xfered_len);
if (xfer != TARGET_XFER_EOF)
return xfer;
return inf_ptrace_target::xfer_partial (object, annex, readbuf, writebuf,
offset, len, xfered_len);
}
static int
linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid)
int
linux_nat_target::thread_alive (ptid_t ptid)
{
/* As long as a PTID is in lwp list, consider it alive. */
return find_lwp_pid (ptid) != NULL;
@ -3921,8 +3950,8 @@ linux_nat_thread_alive (struct target_ops *ops, ptid_t ptid)
/* Implement the to_update_thread_list target method for this
target. */
static void
linux_nat_update_thread_list (struct target_ops *ops)
void
linux_nat_target::update_thread_list ()
{
struct lwp_info *lwp;
@ -3943,8 +3972,8 @@ linux_nat_update_thread_list (struct target_ops *ops)
}
}
static const char *
linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
linux_nat_target::pid_to_str (ptid_t ptid)
{
static char buf[64];
@ -3959,8 +3988,8 @@ linux_nat_pid_to_str (struct target_ops *ops, ptid_t ptid)
return normal_pid_to_str (ptid);
}
static const char *
linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
const char *
linux_nat_target::thread_name (struct thread_info *thr)
{
return linux_proc_tid_get_name (thr->ptid);
}
@ -3968,8 +3997,8 @@ linux_nat_thread_name (struct target_ops *self, struct thread_info *thr)
/* Accepts an integer PID; Returns a string representing a file that
can be opened to get the symbols for the child process. */
static char *
linux_child_pid_to_exec_file (struct target_ops *self, int pid)
char *
linux_nat_target::pid_to_exec_file (int pid)
{
return linux_proc_pid_to_exec_file (pid);
}
@ -3979,7 +4008,7 @@ linux_child_pid_to_exec_file (struct target_ops *self, int pid)
efficient than banging away at PTRACE_PEEKTEXT. */
static enum target_xfer_status
linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
linux_proc_xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, LONGEST len, ULONGEST *xfered_len)
@ -4083,7 +4112,7 @@ spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, ULONGEST len)
object type, using the /proc file system. */
static enum target_xfer_status
linux_proc_xfer_spu (struct target_ops *ops, enum target_object object,
linux_proc_xfer_spu (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
@ -4223,7 +4252,7 @@ linux_proc_pending_signals (int pid, sigset_t *pending,
}
static enum target_xfer_status
linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
linux_nat_xfer_osdata (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
@ -4237,49 +4266,6 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object,
return TARGET_XFER_OK;
}
static enum target_xfer_status
linux_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
enum target_xfer_status xfer;
if (object == TARGET_OBJECT_AUXV)
return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
if (object == TARGET_OBJECT_OSDATA)
return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
if (object == TARGET_OBJECT_SPU)
return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
/* GDB calculates all the addresses in possibly larget width of the address.
Address width needs to be masked before its final use - either by
linux_proc_xfer_partial or inf_ptrace_xfer_partial.
Compare ADDR_BIT first to avoid a compiler warning on shift overflow. */
if (object == TARGET_OBJECT_MEMORY)
{
int addr_bit = gdbarch_addr_bit (target_gdbarch ());
if (addr_bit < (sizeof (ULONGEST) * HOST_CHAR_BIT))
offset &= ((ULONGEST) 1 << addr_bit) - 1;
}
xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
if (xfer != TARGET_XFER_EOF)
return xfer;
return super_xfer_partial (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
}
static void
cleanup_target_stop (void *arg)
{
@ -4291,9 +4277,8 @@ cleanup_target_stop (void *arg)
target_continue_no_signal (*ptid);
}
static std::vector<static_tracepoint_marker>
linux_child_static_tracepoint_markers_by_strid (struct target_ops *self,
const char *strid)
std::vector<static_tracepoint_marker>
linux_nat_target::static_tracepoint_markers_by_strid (const char *strid)
{
char s[IPA_CMD_BUF_SIZE];
struct cleanup *old_chain;
@ -4335,70 +4320,34 @@ linux_child_static_tracepoint_markers_by_strid (struct target_ops *self,
return markers;
}
/* Create a prototype generic GNU/Linux target. The client can override
it with local methods. */
void
linux_target_install_ops (struct target_ops *t)
{
t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
t->to_remove_fork_catchpoint = linux_child_remove_fork_catchpoint;
t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
t->to_remove_vfork_catchpoint = linux_child_remove_vfork_catchpoint;
t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
t->to_remove_exec_catchpoint = linux_child_remove_exec_catchpoint;
t->to_set_syscall_catchpoint = linux_child_set_syscall_catchpoint;
t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
t->to_post_startup_inferior = linux_child_post_startup_inferior;
t->to_post_attach = linux_child_post_attach;
t->to_follow_fork = linux_child_follow_fork;
super_xfer_partial = t->to_xfer_partial;
t->to_xfer_partial = linux_xfer_partial;
t->to_static_tracepoint_markers_by_strid
= linux_child_static_tracepoint_markers_by_strid;
}
struct target_ops *
linux_target (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
linux_target_install_ops (t);
return t;
}
/* target_is_async_p implementation. */
static int
linux_nat_is_async_p (struct target_ops *ops)
int
linux_nat_target::is_async_p ()
{
return linux_is_async_p ();
}
/* target_can_async_p implementation. */
static int
linux_nat_can_async_p (struct target_ops *ops)
int
linux_nat_target::can_async_p ()
{
/* We're always async, unless the user explicitly prevented it with the
"maint set target-async" command. */
return target_async_permitted;
}
static int
linux_nat_supports_non_stop (struct target_ops *self)
int
linux_nat_target::supports_non_stop ()
{
return 1;
}
/* to_always_non_stop_p implementation. */
static int
linux_nat_always_non_stop_p (struct target_ops *self)
int
linux_nat_target::always_non_stop_p ()
{
return 1;
}
@ -4408,14 +4357,14 @@ linux_nat_always_non_stop_p (struct target_ops *self)
int linux_multi_process = 1;
static int
linux_nat_supports_multi_process (struct target_ops *self)
int
linux_nat_target::supports_multi_process ()
{
return linux_multi_process;
}
static int
linux_nat_supports_disable_randomization (struct target_ops *self)
int
linux_nat_target::supports_disable_randomization ()
{
#ifdef HAVE_PERSONALITY
return 1;
@ -4494,8 +4443,8 @@ linux_async_pipe (int enable)
/* target_async implementation. */
static void
linux_nat_async (struct target_ops *ops, int enable)
void
linux_nat_target::async (int enable)
{
if (enable)
{
@ -4563,23 +4512,20 @@ linux_nat_stop_lwp (struct lwp_info *lwp, void *data)
return 0;
}
static void
linux_nat_stop (struct target_ops *self, ptid_t ptid)
void
linux_nat_target::stop (ptid_t ptid)
{
iterate_over_lwps (ptid, linux_nat_stop_lwp, NULL);
}
static void
linux_nat_close (struct target_ops *self)
void
linux_nat_target::close ()
{
/* Unregister from the event loop. */
if (linux_nat_is_async_p (self))
linux_nat_async (self, 0);
if (is_async_p ())
async (0);
if (linux_ops->to_close)
linux_ops->to_close (linux_ops);
super_close (self);
inf_ptrace_target::close ();
}
/* When requests are passed down from the linux-nat layer to the
@ -4589,8 +4535,8 @@ linux_nat_close (struct target_ops *self)
lwpid is a "main" process id or not (it assumes so). We reverse
look up the "main" process id from the lwp here. */
static struct address_space *
linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid)
struct address_space *
linux_nat_target::thread_address_space (ptid_t ptid)
{
struct lwp_info *lwp;
struct inferior *inf;
@ -4616,8 +4562,8 @@ linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid)
/* Return the cached value of the processor core for thread PTID. */
static int
linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
int
linux_nat_target::core_of_thread (ptid_t ptid)
{
struct lwp_info *info = find_lwp_pid (ptid);
@ -4628,8 +4574,8 @@ linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid)
/* Implementation of to_filesystem_is_local. */
static int
linux_nat_filesystem_is_local (struct target_ops *ops)
int
linux_nat_target::filesystem_is_local ()
{
struct inferior *inf = current_inferior ();
@ -4658,11 +4604,10 @@ linux_nat_fileio_pid_of (struct inferior *inf)
/* Implementation of to_fileio_open. */
static int
linux_nat_fileio_open (struct target_ops *self,
struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno)
int
linux_nat_target::fileio_open (struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno)
{
int nat_flags;
mode_t nat_mode;
@ -4685,10 +4630,9 @@ linux_nat_fileio_open (struct target_ops *self,
/* Implementation of to_fileio_readlink. */
static gdb::optional<std::string>
linux_nat_fileio_readlink (struct target_ops *self,
struct inferior *inf, const char *filename,
int *target_errno)
gdb::optional<std::string>
linux_nat_target::fileio_readlink (struct inferior *inf, const char *filename,
int *target_errno)
{
char buf[PATH_MAX];
int len;
@ -4706,10 +4650,9 @@ linux_nat_fileio_readlink (struct target_ops *self,
/* Implementation of to_fileio_unlink. */
static int
linux_nat_fileio_unlink (struct target_ops *self,
struct inferior *inf, const char *filename,
int *target_errno)
int
linux_nat_target::fileio_unlink (struct inferior *inf, const char *filename,
int *target_errno)
{
int ret;
@ -4723,76 +4666,19 @@ linux_nat_fileio_unlink (struct target_ops *self,
/* Implementation of the to_thread_events method. */
static void
linux_nat_thread_events (struct target_ops *ops, int enable)
void
linux_nat_target::thread_events (int enable)
{
report_thread_events = enable;
}
void
linux_nat_add_target (struct target_ops *t)
linux_nat_target::linux_nat_target ()
{
/* Save the provided single-threaded target. We save this in a separate
variable because another target we've inherited from (e.g. inf-ptrace)
may have saved a pointer to T; we want to use it for the final
process stratum target. */
linux_ops_saved = *t;
linux_ops = &linux_ops_saved;
/* Override some methods for multithreading. */
t->to_create_inferior = linux_nat_create_inferior;
t->to_attach = linux_nat_attach;
t->to_detach = linux_nat_detach;
t->to_resume = linux_nat_resume;
t->to_wait = linux_nat_wait;
t->to_pass_signals = linux_nat_pass_signals;
t->to_xfer_partial = linux_nat_xfer_partial;
t->to_kill = linux_nat_kill;
t->to_mourn_inferior = linux_nat_mourn_inferior;
t->to_thread_alive = linux_nat_thread_alive;
t->to_update_thread_list = linux_nat_update_thread_list;
t->to_pid_to_str = linux_nat_pid_to_str;
t->to_thread_name = linux_nat_thread_name;
t->to_has_thread_control = tc_schedlock;
t->to_thread_address_space = linux_nat_thread_address_space;
t->to_stopped_by_watchpoint = linux_nat_stopped_by_watchpoint;
t->to_stopped_data_address = linux_nat_stopped_data_address;
t->to_stopped_by_sw_breakpoint = linux_nat_stopped_by_sw_breakpoint;
t->to_supports_stopped_by_sw_breakpoint = linux_nat_supports_stopped_by_sw_breakpoint;
t->to_stopped_by_hw_breakpoint = linux_nat_stopped_by_hw_breakpoint;
t->to_supports_stopped_by_hw_breakpoint = linux_nat_supports_stopped_by_hw_breakpoint;
t->to_thread_events = linux_nat_thread_events;
t->to_can_async_p = linux_nat_can_async_p;
t->to_is_async_p = linux_nat_is_async_p;
t->to_supports_non_stop = linux_nat_supports_non_stop;
t->to_always_non_stop_p = linux_nat_always_non_stop_p;
t->to_async = linux_nat_async;
super_close = t->to_close;
t->to_close = linux_nat_close;
t->to_stop = linux_nat_stop;
t->to_supports_multi_process = linux_nat_supports_multi_process;
t->to_supports_disable_randomization
= linux_nat_supports_disable_randomization;
t->to_core_of_thread = linux_nat_core_of_thread;
t->to_filesystem_is_local = linux_nat_filesystem_is_local;
t->to_fileio_open = linux_nat_fileio_open;
t->to_fileio_readlink = linux_nat_fileio_readlink;
t->to_fileio_unlink = linux_nat_fileio_unlink;
/* We don't change the stratum; this target will sit at
process_stratum and thread_db will set at thread_stratum. This
is a little strange, since this is a multi-threaded-capable
target, but we want to be on the stack below thread_db, and we
also want to be used for single-threaded processes. */
add_target (t);
}
/* Register a method to call whenever a new thread is attached. */

View File

@ -18,9 +18,138 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "nat/linux-nat.h"
#include "inf-ptrace.h"
#include "target.h"
#include <signal.h>
/* A prototype generic GNU/Linux target. A concrete instance should
override it with local methods. */
class linux_nat_target : public inf_ptrace_target
{
public:
linux_nat_target ();
~linux_nat_target () override = 0;
thread_control_capabilities get_thread_control_capabilities () override
{ return tc_schedlock; }
void create_inferior (const char *, const std::string &,
char **, int) override;
void attach (const char *, int) override;
void detach (inferior *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void pass_signals (int, unsigned char *) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void kill () override;
void mourn_inferior () override;
int thread_alive (ptid_t ptid) override;
void update_thread_list () override;
const char *pid_to_str (ptid_t) override;
const char *thread_name (struct thread_info *) override;
struct address_space *thread_address_space (ptid_t) override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int stopped_by_sw_breakpoint () override;
int supports_stopped_by_sw_breakpoint () override;
int stopped_by_hw_breakpoint () override;
int supports_stopped_by_hw_breakpoint () override;
void thread_events (int) override;
int can_async_p () override;
int is_async_p () override;
int supports_non_stop () override;
int always_non_stop_p () override;
void async (int) override;
void close () override;
void stop (ptid_t) override;
int supports_multi_process () override;
int supports_disable_randomization () override;
int core_of_thread (ptid_t ptid) override;
int filesystem_is_local () override;
int fileio_open (struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno) override;
gdb::optional<std::string>
fileio_readlink (struct inferior *inf,
const char *filename,
int *target_errno) override;
int fileio_unlink (struct inferior *inf,
const char *filename,
int *target_errno) override;
int insert_fork_catchpoint (int) override;
int remove_fork_catchpoint (int) override;
int insert_vfork_catchpoint (int) override;
int remove_vfork_catchpoint (int) override;
int insert_exec_catchpoint (int) override;
int remove_exec_catchpoint (int) override;
int set_syscall_catchpoint (int pid, bool needed, int any_count,
gdb::array_view<const int> syscall_counts) override;
char *pid_to_exec_file (int pid) override;
void post_startup_inferior (ptid_t) override;
void post_attach (int) override;
int follow_fork (int, int) override;
std::vector<static_tracepoint_marker>
static_tracepoint_markers_by_strid (const char *id) override;
/* Methods that are meant to overridden by the concrete
arch-specific target instance. */
virtual void low_resume (ptid_t ptid, int step, enum gdb_signal sig)
{ inf_ptrace_target::resume (ptid, step, sig); }
virtual int low_stopped_by_watchpoint ()
{ return 0; }
virtual int low_stopped_data_address (CORE_ADDR *addr_p)
{ return 0; }
};
/* The final/concrete instance. */
extern linux_nat_target *linux_target;
struct arch_lwp_info;
/* Structure describing an LWP. This is public only for the purposes
@ -149,18 +278,6 @@ extern void linux_stop_and_wait_all_lwps (void);
left stopped.) */
extern void linux_unstop_all_lwps (void);
/* Create a prototype generic GNU/Linux target. The client can
override it with local methods. */
struct target_ops * linux_target (void);
/* Make a prototype generic GNU/Linux target. The client can override
it with local methods. */
void linux_target_install_ops (struct target_ops *t);
/* Register the customized GNU/Linux target. This should be used
instead of calling add_target directly. */
void linux_nat_add_target (struct target_ops *);
/* Register a method to call whenever a new thread is attached. */
void linux_nat_set_new_thread (struct target_ops *, void (*) (struct lwp_info *));

View File

@ -402,8 +402,8 @@ linux_is_uclinux (void)
{
CORE_ADDR dummy;
return (target_auxv_search (&current_target, AT_NULL, &dummy) > 0
&& target_auxv_search (&current_target, AT_PAGESZ, &dummy) == 0);
return (target_auxv_search (target_stack, AT_NULL, &dummy) > 0
&& target_auxv_search (target_stack, AT_PAGESZ, &dummy) == 0);
}
static int
@ -1423,7 +1423,7 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
/* Determine list of SPU ids. */
gdb::optional<gdb::byte_vector>
spu_ids = target_read_alloc (&current_target, TARGET_OBJECT_SPU, NULL);
spu_ids = target_read_alloc (target_stack, TARGET_OBJECT_SPU, NULL);
if (!spu_ids)
return note_data;
@ -1439,7 +1439,7 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[j]);
gdb::optional<gdb::byte_vector> spu_data
= target_read_alloc (&current_target, TARGET_OBJECT_SPU, annex);
= target_read_alloc (target_stack, TARGET_OBJECT_SPU, annex);
if (spu_data && !spu_data->empty ())
{
@ -1661,7 +1661,7 @@ linux_get_siginfo_data (thread_info *thread, struct gdbarch *gdbarch)
gdb::byte_vector buf (TYPE_LENGTH (siginfo_type));
bytes_read = target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
bytes_read = target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
buf.data (), 0, TYPE_LENGTH (siginfo_type));
if (bytes_read != TYPE_LENGTH (siginfo_type))
buf.clear ();
@ -1970,7 +1970,7 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
/* Auxillary vector. */
gdb::optional<gdb::byte_vector> auxv =
target_read_alloc (&current_target, TARGET_OBJECT_AUXV, NULL);
target_read_alloc (target_stack, TARGET_OBJECT_AUXV, NULL);
if (auxv && !auxv->empty ())
{
note_data = elfcore_write_note (obfd, note_data, note_size,
@ -2253,7 +2253,7 @@ linux_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range *range)
char filename[100];
long pid;
if (target_auxv_search (&current_target, AT_SYSINFO_EHDR, &range->start) <= 0)
if (target_auxv_search (target_stack, AT_SYSINFO_EHDR, &range->start) <= 0)
return 0;
/* It doesn't make sense to access the host's /proc when debugging a
@ -2443,14 +2443,14 @@ linux_displaced_step_location (struct gdbarch *gdbarch)
local-store address and is thus not usable as displaced stepping
location. The auxiliary vector gets us the PowerPC-side entry
point address instead. */
if (target_auxv_search (&current_target, AT_ENTRY, &addr) <= 0)
if (target_auxv_search (target_stack, AT_ENTRY, &addr) <= 0)
throw_error (NOT_SUPPORTED_ERROR,
_("Cannot find AT_ENTRY auxiliary vector entry."));
/* Make certain that the address points at real code, and not a
function descriptor. */
addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
&current_target);
target_stack);
/* Inferior calls also use the entry point as a breakpoint location.
We don't want displaced stepping to interfere with those

View File

@ -75,6 +75,40 @@
of the ptid_t prevents thread IDs changing when libpthread is
loaded or unloaded. */
class thread_db_target final : public target_ops
{
public:
thread_db_target ();
const char *shortname () override
{ return "multi-thread"; }
const char *longname () override
{ return _("multi-threaded child process."); }
const char *doc () override
{ return _("Threads and pthreads support."); }
void detach (inferior *, int) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
void mourn_inferior () override;
void update_thread_list () override;
const char *pid_to_str (ptid_t) override;
CORE_ADDR get_thread_local_address (ptid_t ptid,
CORE_ADDR load_module_addr,
CORE_ADDR offset) override;
const char *extra_thread_info (struct thread_info *) override;
ptid_t get_ada_task_ptid (long lwp, long thread) override;
thread_info *thread_handle_to_thread_info (const gdb_byte *thread_handle,
int handle_len,
inferior *inf) override;
};
thread_db_target::thread_db_target ()
{
this->to_stratum = thread_stratum;
}
static char *libthread_db_search_path;
/* Set to non-zero if thread_db auto-loading is enabled
@ -118,7 +152,7 @@ show_libthread_db_debug (struct ui_file *file, int from_tty,
threads. */
/* This module's target vector. */
static struct target_ops thread_db_ops;
static thread_db_target the_thread_db_target;
/* Non-zero if we have determined the signals used by the threads
library. */
@ -635,7 +669,7 @@ try_thread_db_load_1 (struct thread_db_info *info)
/* The thread library was detected. Activate the thread_db target
if this is the first process using it. */
if (thread_db_list->next == NULL)
push_target (&thread_db_ops);
push_target (&the_thread_db_target);
return 1;
}
@ -889,7 +923,7 @@ thread_db_load (void)
return 0;
/* Don't attempt to use thread_db for remote targets. */
if (!(target_can_run (&current_target) || core_bfd))
if (!(target_can_run () || core_bfd))
return 0;
if (thread_db_load_search ())
@ -980,7 +1014,7 @@ static void
check_pid_namespace_match (void)
{
/* Check is only relevant for local targets targets. */
if (target_can_run (&current_target))
if (target_can_run ())
{
/* If the child is in a different PID namespace, its idea of its
PID will differ from our idea of its PID. When we scan the
@ -1055,32 +1089,31 @@ record_thread (struct thread_db_info *info,
return tp;
}
static void
thread_db_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
thread_db_target::detach (inferior *inf, int from_tty)
{
struct target_ops *target_beneath = find_target_beneath (ops);
struct target_ops *target_beneath = find_target_beneath (this);
delete_thread_db_info (inf->pid);
target_beneath->to_detach (target_beneath, inf, from_tty);
target_beneath->detach (inf, from_tty);
/* NOTE: From this point on, inferior_ptid is null_ptid. */
/* If there are no more processes using libpthread, detach the
thread_db target ops. */
if (!thread_db_list)
unpush_target (&thread_db_ops);
unpush_target (this);
}
static ptid_t
thread_db_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus,
int options)
ptid_t
thread_db_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int options)
{
struct thread_db_info *info;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
ptid = beneath->to_wait (beneath, ptid, ourstatus, options);
ptid = beneath->wait (ptid, ourstatus, options);
switch (ourstatus->kind)
{
@ -1103,7 +1136,7 @@ thread_db_wait (struct target_ops *ops,
not unless we find otherwise. */
delete_thread_db_info (ptid_get_pid (ptid));
if (!thread_db_list)
unpush_target (&thread_db_ops);
unpush_target (&the_thread_db_target);
return ptid;
}
@ -1114,18 +1147,18 @@ thread_db_wait (struct target_ops *ops,
return ptid;
}
static void
thread_db_mourn_inferior (struct target_ops *ops)
void
thread_db_target::mourn_inferior ()
{
struct target_ops *target_beneath = find_target_beneath (ops);
struct target_ops *target_beneath = find_target_beneath (this);
delete_thread_db_info (ptid_get_pid (inferior_ptid));
target_beneath->to_mourn_inferior (target_beneath);
target_beneath->mourn_inferior ();
/* Detach thread_db target ops. */
if (!thread_db_list)
unpush_target (ops);
unpush_target (&the_thread_db_target);
}
struct callback_data
@ -1293,8 +1326,8 @@ thread_db_find_new_threads_1 (ptid_t ptid)
/* Implement the to_update_thread_list target method for this
target. */
static void
thread_db_update_thread_list (struct target_ops *ops)
void
thread_db_target::update_thread_list ()
{
struct thread_db_info *info;
struct inferior *inf;
@ -1334,11 +1367,11 @@ thread_db_update_thread_list (struct target_ops *ops)
}
/* Give the beneath target a chance to do extra processing. */
ops->beneath->to_update_thread_list (ops->beneath);
this->beneath->update_thread_list ();
}
static const char *
thread_db_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
thread_db_target::pid_to_str (ptid_t ptid)
{
struct thread_info *thread_info = find_thread_ptid (ptid);
struct target_ops *beneath;
@ -1354,16 +1387,15 @@ thread_db_pid_to_str (struct target_ops *ops, ptid_t ptid)
return buf;
}
beneath = find_target_beneath (ops);
return beneath->to_pid_to_str (beneath, ptid);
beneath = find_target_beneath (this);
return beneath->pid_to_str (ptid);
}
/* Return a string describing the state of the thread specified by
INFO. */
static const char *
thread_db_extra_thread_info (struct target_ops *self,
struct thread_info *info)
const char *
thread_db_target::extra_thread_info (thread_info *info)
{
if (info->priv == NULL)
return NULL;
@ -1379,11 +1411,10 @@ thread_db_extra_thread_info (struct target_ops *self,
/* Return pointer to the thread_info struct which corresponds to
THREAD_HANDLE (having length HANDLE_LEN). */
static struct thread_info *
thread_db_thread_handle_to_thread_info (struct target_ops *ops,
const gdb_byte *thread_handle,
int handle_len,
struct inferior *inf)
thread_info *
thread_db_target::thread_handle_to_thread_info (const gdb_byte *thread_handle,
int handle_len,
inferior *inf)
{
struct thread_info *tp;
thread_t handle_tid;
@ -1412,11 +1443,10 @@ thread_db_thread_handle_to_thread_info (struct target_ops *ops,
/* Get the address of the thread local variable in load module LM which
is stored at OFFSET within the thread local storage for thread PTID. */
static CORE_ADDR
thread_db_get_thread_local_address (struct target_ops *ops,
ptid_t ptid,
CORE_ADDR lm,
CORE_ADDR offset)
CORE_ADDR
thread_db_target::get_thread_local_address (ptid_t ptid,
CORE_ADDR lm,
CORE_ADDR offset)
{
struct thread_info *thread_info;
struct target_ops *beneath;
@ -1491,24 +1521,23 @@ thread_db_get_thread_local_address (struct target_ops *ops,
: (CORE_ADDR) (uintptr_t) address);
}
beneath = find_target_beneath (ops);
return beneath->to_get_thread_local_address (beneath, ptid, lm, offset);
beneath = find_target_beneath (this);
return beneath->get_thread_local_address (ptid, lm, offset);
}
/* Implement the to_get_ada_task_ptid target method for this target. */
static ptid_t
thread_db_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
ptid_t
thread_db_target::get_ada_task_ptid (long lwp, long thread)
{
/* NPTL uses a 1:1 model, so the LWP id suffices. */
return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
}
static void
thread_db_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signo)
void
thread_db_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
struct thread_db_info *info;
if (ptid_equal (ptid, minus_one_ptid))
@ -1522,7 +1551,7 @@ thread_db_resume (struct target_ops *ops,
if (info)
info->need_stale_parent_threads_check = 0;
beneath->to_resume (beneath, ptid, step, signo);
beneath->resume (ptid, step, signo);
}
/* std::sort helper function for info_auto_load_libthread_db, sort the
@ -1637,35 +1666,9 @@ info_auto_load_libthread_db (const char *args, int from_tty)
uiout->message (_("No auto-loaded libthread-db.\n"));
}
static void
init_thread_db_ops (void)
{
thread_db_ops.to_shortname = "multi-thread";
thread_db_ops.to_longname = "multi-threaded child process.";
thread_db_ops.to_doc = "Threads and pthreads support.";
thread_db_ops.to_detach = thread_db_detach;
thread_db_ops.to_wait = thread_db_wait;
thread_db_ops.to_resume = thread_db_resume;
thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
thread_db_ops.to_update_thread_list = thread_db_update_thread_list;
thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
thread_db_ops.to_stratum = thread_stratum;
thread_db_ops.to_has_thread_control = tc_schedlock;
thread_db_ops.to_get_thread_local_address
= thread_db_get_thread_local_address;
thread_db_ops.to_extra_thread_info = thread_db_extra_thread_info;
thread_db_ops.to_get_ada_task_ptid = thread_db_get_ada_task_ptid;
thread_db_ops.to_thread_handle_to_thread_info = thread_db_thread_handle_to_thread_info;
thread_db_ops.to_magic = OPS_MAGIC;
complete_target_initialization (&thread_db_ops);
}
void
_initialize_thread_db (void)
{
init_thread_db_ops ();
/* Defer loading of libthread_db.so until inferior is running.
This allows gdb to load correct libthread_db for a given
executable -- there could be multiple versions of glibc,

View File

@ -34,7 +34,15 @@
#include "m32r-tdep.h"
class m32r_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static m32r_linux_nat_target the_m32r_linux_nat_target;
/* Since EVB register is not available for native debug, we reduce
the number of registers. */
@ -191,9 +199,8 @@ fill_fpregset (const struct regcache *regcache,
this for all registers (including the floating point and SSE
registers). */
static void
m32r_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
m32r_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -213,9 +220,8 @@ m32r_linux_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating point and SSE
registers). */
static void
m32r_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
m32r_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -234,15 +240,7 @@ m32r_linux_store_inferior_registers (struct target_ops *ops,
void
_initialize_m32r_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Add our register access methods. */
t->to_fetch_registers = m32r_linux_fetch_inferior_registers;
t->to_store_registers = m32r_linux_store_inferior_registers;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_m32r_linux_nat_target;
add_target (&the_m32r_linux_nat_target);
}

View File

@ -29,6 +29,14 @@
#include "m68k-tdep.h"
#include "inf-ptrace.h"
struct m68k_bsd_nat_target final : public inf_ptrace_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static m68k_bsd_nat_target the_m68k_bsd_nat_target;
static int
m68kbsd_gregset_supplies_p (int regnum)
{
@ -107,9 +115,8 @@ m68kbsd_collect_fpregset (struct regcache *regcache,
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers (including the floating-point registers). */
static void
m68kbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
m68k_bsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -137,9 +144,8 @@ m68kbsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers (including the floating-point registers). */
static void
m68kbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
m68k_bsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -219,12 +225,7 @@ m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
void
_initialize_m68kbsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = m68kbsd_fetch_inferior_registers;
t->to_store_registers = m68kbsd_store_inferior_registers;
add_target (t);
add_target (&the_m68k_bsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (m68kbsd_supply_pcb);

View File

@ -57,6 +57,17 @@
#define PTRACE_GET_THREAD_AREA 25
#endif
class m68k_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static m68k_linux_nat_target the_m68k_linux_nat_target;
/* This table must line up with gdbarch_register_name in "m68k-tdep.c". */
static const int regmap[] =
{
@ -392,9 +403,8 @@ static void store_fpregs (const struct regcache *regcache, int tid, int regno)
this for all registers (including the floating point and SSE
registers). */
static void
m68k_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
m68k_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
pid_t tid;
@ -446,9 +456,8 @@ m68k_linux_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating point and SSE
registers). */
static void
m68k_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
m68k_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
pid_t tid;
@ -509,15 +518,7 @@ ps_get_thread_area (struct ps_prochandle *ph,
void
_initialize_m68k_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Add our register access methods. */
t->to_fetch_registers = m68k_linux_fetch_inferior_registers;
t->to_store_registers = m68k_linux_store_inferior_registers;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_m68k_linux_nat_target;
add_target (&the_m68k_linux_nat_target);
}

View File

@ -30,16 +30,27 @@ $ENDER = qr,^\s*};$,;
# Match a C symbol.
$SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_]*,;
# Match the name part of a method in struct target_ops.
$NAME_PART = qr,\(\*(?<name>${SYMBOL}+)\)\s,;
$NAME_PART = qr,(?<name>${SYMBOL}+)\s,;
# Match the arguments to a method.
$ARGS_PART = qr,(?<args>\(.*\)),;
# We strip the indentation so here we only need the caret.
$INTRO_PART = qr,^,;
$POINTER_PART = qr,\s*(\*)?\s*,;
# Match a C++ symbol, including scope operators and template
# parameters. E.g., 'std::vector<something>'.
$CP_SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_<>:]*,;
# Match the return type when it is "ordinary".
$SIMPLE_RETURN_PART = qr,[^\(]+,;
$SIMPLE_RETURN_PART = qr,((struct|class|enum|union)\s+)?${CP_SYMBOL}+,;
# Match the return type when it is a VEC.
$VEC_RETURN_PART = qr,VEC\s*\([^\)]+\)[^\(]*,;
$VEC_RETURN_PART = qr,VEC\s*\([^\)]+\),;
# Match a return type.
$RETURN_PART = qr,((const|volatile)\s+)?(${SIMPLE_RETURN_PART}|${VEC_RETURN_PART})${POINTER_PART},;
# Match "virtual".
$VIRTUAL_PART = qr,virtual\s,;
# Match the TARGET_DEFAULT_* attribute for a method.
$TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*)\),;
@ -49,8 +60,7 @@ $TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*
$METHOD_TRAILER = qr,\s*${TARGET_DEFAULT_PART}$,;
# Match an entire method definition.
$METHOD = ($INTRO_PART . "(?<return_type>" . $SIMPLE_RETURN_PART
. "|" . $VEC_RETURN_PART . ")"
$METHOD = ($INTRO_PART . $VIRTUAL_PART . "(?<return_type>" . $RETURN_PART . ")"
. $NAME_PART . $ARGS_PART
. $METHOD_TRAILER);
@ -90,7 +100,7 @@ sub scan_target_h() {
next if /{/;
last if m/$ENDER/;
# Just in case somebody ever uses C99.
# Strip // comments.
$_ =~ s,//.*$,,;
$_ = trim ($_);
@ -130,16 +140,24 @@ sub parse_argtypes($) {
sub dname($) {
my ($name) = @_;
$name =~ s/to_/delegate_/;
return $name;
return "target_ops::" . $name;
}
# Write function header given name, return type, and argtypes.
# Returns a list of actual argument names.
sub write_function_header($$@) {
my ($name, $return_type, @argtypes) = @_;
sub write_function_header($$$@) {
my ($decl, $name, $return_type, @argtypes) = @_;
print $return_type;
if ($decl) {
if ($return_type !~ m,\*$,) {
print " ";
}
} else {
print "\n";
}
print "static " . $return_type . "\n";
print $name . ' (';
my $iter;
@ -156,12 +174,7 @@ sub write_function_header($$@) {
}
my $vname;
if ($i == 0) {
# Just a random nicety.
$vname = 'self';
} else {
$vname .= "arg$i";
}
$vname .= "arg$i";
$val .= $vname;
push @argdecls, $val;
@ -169,25 +182,36 @@ sub write_function_header($$@) {
++$i;
}
print join (', ', @argdecls) . ")\n";
print "{\n";
print join (', ', @argdecls) . ")";
if ($decl) {
print " override;\n";
} else {
print "\n{\n";
}
return @actuals;
}
# Write out a declaration.
sub write_declaration($$@) {
my ($name, $return_type, @argtypes) = @_;
write_function_header (1, $name, $return_type, @argtypes);
}
# Write out a delegation function.
sub write_delegator($$@) {
my ($name, $return_type, @argtypes) = @_;
my (@names) = write_function_header (dname ($name), $return_type,
@argtypes);
my (@names) = write_function_header (0, dname ($name),
$return_type, @argtypes);
print " $names[0] = $names[0]->beneath;\n";
print " ";
if ($return_type ne 'void') {
print "return ";
}
print "$names[0]->" . $name . " (";
print "this->beneath->" . $name . " (";
print join (', ', @names);
print ");\n";
print "}\n\n";
@ -195,21 +219,28 @@ sub write_delegator($$@) {
sub tdname ($) {
my ($name) = @_;
$name =~ s/to_/tdefault_/;
return $name;
return "dummy_target::" . $name;
}
# Write out a default function.
sub write_tdefault($$$$@) {
my ($content, $style, $name, $return_type, @argtypes) = @_;
my (@names) = write_function_header (0, tdname ($name),
$return_type, @argtypes);
if ($style eq 'FUNC') {
return $content;
}
write_function_header (tdname ($name), $return_type, @argtypes);
if ($style eq 'RETURN') {
print " ";
if ($return_type ne 'void') {
print "return ";
}
print $content . " (this";
if (@names) {
print ", ";
}
print join (', ', @names);
print ");\n";
} elsif ($style eq 'RETURN') {
print " return $content;\n";
} elsif ($style eq 'NORETURN') {
print " $content;\n";
@ -252,39 +283,37 @@ sub munge_type($) {
}
# Write out a debug method.
sub write_debugmethod($$$$@) {
my ($content, $style, $name, $return_type, @argtypes) = @_;
sub write_debugmethod($$$@) {
my ($content, $name, $return_type, @argtypes) = @_;
my ($debugname) = $name;
$debugname =~ s/to_/debug_/;
my ($debugname) = "debug_target::" . $name;
my ($targetname) = $name;
$targetname =~ s/to_/target_/;
my (@names) = write_function_header ($debugname, $return_type, @argtypes);
my (@names) = write_function_header (0, $debugname, $return_type, @argtypes);
if ($return_type ne 'void') {
print " $return_type result;\n";
}
print " fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", debug_target.to_shortname);\n";
print " fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", this->beneath->shortname ());\n";
# Delegate to the beneath target.
print " ";
if ($return_type ne 'void') {
print "result = ";
}
print "debug_target." . $name . " (";
my @names2 = @names;
@names2[0] = "&debug_target";
print join (', ', @names2);
print "this->beneath->" . $name . " (";
print join (', ', @names);
print ");\n";
# Now print the arguments.
print " fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", debug_target.to_shortname);\n";
print " fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", this->beneath->shortname ());\n";
for my $i (0 .. $#argtypes) {
print " fputs_unfiltered (\", \", gdb_stdlog);\n" if $i > 0;
if ($i > 0) {
print " fputs_unfiltered (\", \", gdb_stdlog);\n"
}
my $printer = munge_type ($argtypes[$i]);
print " $printer ($names2[$i]);\n";
print " $printer ($names[$i]);\n";
}
if ($return_type ne 'void') {
print " fputs_unfiltered (\") = \", gdb_stdlog);\n";
@ -308,61 +337,71 @@ print "/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */\n";
print "/* vi:set ro: */\n\n";
print "/* To regenerate this file, run:*/\n";
print "/* make-target-delegates target.h > target-delegates.c */\n";
print "\n";
@lines = scan_target_h();
%tdefault_names = ();
%debug_names = ();
@delegators = ();
@return_types = ();
@tdefaults = ();
@styles = ();
@argtypes_array = ();
foreach $current_line (@lines) {
next unless $current_line =~ m/$METHOD/;
$name = $+{name};
$current_line = $+{args};
$return_type = trim ($+{return_type});
$current_args = $+{args};
$tdefault = $+{default_arg};
$style = $+{style};
my $name = $+{name};
my $current_line = $+{args};
my $return_type = trim ($+{return_type});
my $current_args = $+{args};
my $tdefault = $+{default_arg};
my $style = $+{style};
@argtypes = parse_argtypes ($current_args);
my @argtypes = parse_argtypes ($current_args);
# The first argument must be "this" to be delegatable.
if ($argtypes[0] =~ /\s*struct\s+target_ops\s*\*\s*/) {
write_delegator ($name, $return_type, @argtypes);
push @delegators, $name;
push @delegators, $name;
$return_types{$name} = $return_type;
$tdefaults{$name} = $tdefault;
$styles{$name} = $style;
$argtypes_array{$name} = \@argtypes;
}
$tdefault_names{$name} = write_tdefault ($tdefault, $style,
$name, $return_type,
@argtypes);
sub print_class($) {
my ($name) = @_;
$debug_names{$name} = write_debugmethod ($tdefault, $style,
$name, $return_type,
@argtypes);
print "struct " . $name . " : public target_ops\n";
print "{\n";
print " $name ();\n";
print "\n";
print " const char *shortname () override;\n";
print " const char *longname () override;\n";
print " const char *doc () override;\n";
print "\n";
for $name (@delegators) {
my $return_type = $return_types{$name};
my @argtypes = @{$argtypes_array{$name}};
print " ";
write_declaration ($name, $return_type, @argtypes);
}
print "};\n\n";
}
# Now the delegation code.
print "static void\ninstall_delegators (struct target_ops *ops)\n{\n";
print_class ("dummy_target");
print_class ("debug_target");
for $iter (@delegators) {
print " if (ops->" . $iter . " == NULL)\n";
print " ops->" . $iter . " = " . dname ($iter) . ";\n";
for $name (@delegators) {
my $tdefault = $tdefaults{$name};
my $return_type = $return_types{$name};
my $style = $styles{$name};
my @argtypes = @{$argtypes_array{$name}};
write_delegator ($name, $return_type, @argtypes);
write_tdefault ($tdefault, $style, $name, $return_type, @argtypes);
write_debugmethod ($tdefault, $name, $return_type, @argtypes);
}
print "}\n\n";
# Now the default method code.
print "static void\ninstall_dummy_methods (struct target_ops *ops)\n{\n";
for $iter (@delegators) {
print " ops->" . $iter . " = " . $tdefault_names{$iter} . ";\n";
}
print "}\n\n";
# The debug method code.
print "static void\ninit_debug_target (struct target_ops *ops)\n{\n";
for $iter (@delegators) {
print " ops->" . $iter . " = " . $debug_names{$iter} . ";\n";
}
print "}\n";

View File

@ -266,7 +266,7 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
static void
exec_continue (char **argv, int argc)
{
prepare_execution_command (&current_target, mi_async_p ());
prepare_execution_command (target_stack, mi_async_p ());
if (non_stop)
{
@ -405,7 +405,7 @@ run_one_inferior (struct inferior *inf, void *arg)
int start_p = *(int *) arg;
const char *run_cmd = start_p ? "start" : "run";
struct target_ops *run_target = find_run_target ();
int async_p = mi_async && run_target->to_can_async_p (run_target);
int async_p = mi_async && run_target->can_async_p ();
if (inf->pid != 0)
{
@ -479,7 +479,7 @@ mi_cmd_exec_run (const char *command, char **argv, int argc)
{
const char *run_cmd = start_p ? "start" : "run";
struct target_ops *run_target = find_run_target ();
int async_p = mi_async && run_target->to_can_async_p (run_target);
int async_p = mi_async && run_target->can_async_p ();
mi_execute_cli_command (run_cmd, async_p,
async_p ? "&" : NULL);
@ -1353,10 +1353,7 @@ mi_cmd_data_read_memory (const char *command, char **argv, int argc)
gdb::byte_vector mbuf (total_bytes);
/* Dispatch memory reads to the topmost target, not the flattened
current_target. */
nr_bytes = target_read (current_target.beneath,
TARGET_OBJECT_MEMORY, NULL, mbuf.data (),
nr_bytes = target_read (target_stack, TARGET_OBJECT_MEMORY, NULL, mbuf.data (),
addr, total_bytes);
if (nr_bytes <= 0)
error (_("Unable to read memory."));
@ -1476,7 +1473,7 @@ mi_cmd_data_read_memory_bytes (const char *command, char **argv, int argc)
length = atol (argv[1]);
std::vector<memory_read_result> result
= read_memory_robust (current_target.beneath, addr, length);
= read_memory_robust (target_stack, addr, length);
if (result.size () == 0)
error (_("Unable to read memory."));

View File

@ -74,7 +74,7 @@ msymbol_is_function (struct objfile *objfile, minimal_symbol *minsym,
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
CORE_ADDR pc = gdbarch_convert_from_func_ptr_addr (gdbarch, msym_addr,
&current_target);
target_stack);
if (pc != msym_addr)
{
if (func_address_p != NULL)

View File

@ -31,6 +31,14 @@
#include "mips-fbsd-tdep.h"
#include "inf-ptrace.h"
struct mips_fbsd_nat_target final : public fbsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static mips_fbsd_nat_target the_mips_fbsd_nat_target;
/* Determine if PT_GETREGS fetches REGNUM. */
static bool
@ -52,9 +60,8 @@ getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
mips_fbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
mips_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -84,9 +91,8 @@ mips_fbsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
static void
mips_fbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
mips_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -123,10 +129,5 @@ mips_fbsd_store_inferior_registers (struct target_ops *ops,
void
_initialize_mips_fbsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = mips_fbsd_fetch_inferior_registers;
t->to_store_registers = mips_fbsd_store_inferior_registers;
fbsd_nat_add_target (t);
add_target (&the_mips_fbsd_nat_target);
}

View File

@ -42,20 +42,50 @@
#define PTRACE_GET_THREAD_AREA 25
#endif
class mips_linux_nat_target final : public linux_nat_trad_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
void close () override;
int can_use_hw_breakpoint (enum bptype, int, int) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
const struct target_desc *read_description () override;
protected:
/* Override linux_nat_trad_target methods. */
CORE_ADDR register_u_offset (struct gdbarch *gdbarch,
int regno, int store_p) override;
private:
/* Helpers. See definitions. */
void mips64_regsets_store_registers (struct regcache *regcache,
int regno);
void mips64_regsets_fetch_registers (struct regcache *regcache,
int regno);
};
static mips_linux_nat_target the_mips_linux_nat_target;
/* Assume that we have PTRACE_GETREGS et al. support. If we do not,
we'll clear this and use PTRACE_PEEKUSER instead. */
static int have_ptrace_regsets = 1;
/* Saved function pointers to fetch and store a single register using
PTRACE_PEEKUSER and PTRACE_POKEUSER. */
static void (*super_fetch_registers) (struct target_ops *,
struct regcache *, int);
static void (*super_store_registers) (struct target_ops *,
struct regcache *, int);
static void (*super_close) (struct target_ops *);
/* Map gdb internal register number to ptrace ``address''.
These ``addresses'' are normally defined in <asm/ptrace.h>.
@ -208,9 +238,9 @@ fill_fpregset (const struct regcache *regcache,
/* Fetch REGNO (or all registers if REGNO == -1) from the target
using PTRACE_GETREGS et al. */
static void
mips64_linux_regsets_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
mips_linux_nat_target::mips64_regsets_fetch_registers
(struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
int is_fp, is_dsp;
@ -280,23 +310,24 @@ mips64_linux_regsets_fetch_registers (struct target_ops *ops,
}
if (is_dsp)
super_fetch_registers (ops, regcache, regno);
linux_nat_trad_target::fetch_registers (regcache, regno);
else if (regno == -1 && have_dsp)
{
for (regi = mips_regnum (gdbarch)->dspacc;
regi < mips_regnum (gdbarch)->dspacc + 6;
regi++)
super_fetch_registers (ops, regcache, regi);
super_fetch_registers (ops, regcache, mips_regnum (gdbarch)->dspctl);
linux_nat_trad_target::fetch_registers (regcache, regi);
linux_nat_trad_target::fetch_registers (regcache,
mips_regnum (gdbarch)->dspctl);
}
}
/* Store REGNO (or all registers if REGNO == -1) to the target
using PTRACE_SETREGS et al. */
static void
mips64_linux_regsets_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
mips_linux_nat_target::mips64_regsets_store_registers
(struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
int is_fp, is_dsp;
@ -357,56 +388,56 @@ mips64_linux_regsets_store_registers (struct target_ops *ops,
}
if (is_dsp)
super_store_registers (ops, regcache, regno);
linux_nat_trad_target::store_registers (regcache, regno);
else if (regno == -1 && have_dsp)
{
for (regi = mips_regnum (gdbarch)->dspacc;
regi < mips_regnum (gdbarch)->dspacc + 6;
regi++)
super_store_registers (ops, regcache, regi);
super_store_registers (ops, regcache, mips_regnum (gdbarch)->dspctl);
linux_nat_trad_target::store_registers (regcache, regi);
linux_nat_trad_target::store_registers (regcache,
mips_regnum (gdbarch)->dspctl);
}
}
/* Fetch REGNO (or all registers if REGNO == -1) from the target
using any working method. */
static void
mips64_linux_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
mips_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
/* Unless we already know that PTRACE_GETREGS does not work, try it. */
if (have_ptrace_regsets)
mips64_linux_regsets_fetch_registers (ops, regcache, regnum);
mips64_regsets_fetch_registers (regcache, regnum);
/* If we know, or just found out, that PTRACE_GETREGS does not work, fall
back to PTRACE_PEEKUSER. */
if (!have_ptrace_regsets)
super_fetch_registers (ops, regcache, regnum);
linux_nat_trad_target::fetch_registers (regcache, regnum);
}
/* Store REGNO (or all registers if REGNO == -1) to the target
using any working method. */
static void
mips64_linux_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
mips_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
{
/* Unless we already know that PTRACE_GETREGS does not work, try it. */
if (have_ptrace_regsets)
mips64_linux_regsets_store_registers (ops, regcache, regnum);
mips64_regsets_store_registers (regcache, regnum);
/* If we know, or just found out, that PTRACE_GETREGS does not work, fall
back to PTRACE_PEEKUSER. */
if (!have_ptrace_regsets)
super_store_registers (ops, regcache, regnum);
linux_nat_trad_target::store_registers (regcache, regnum);
}
/* Return the address in the core dump or inferior of register
REGNO. */
static CORE_ADDR
mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
CORE_ADDR
mips_linux_nat_target::register_u_offset (struct gdbarch *gdbarch,
int regno, int store_p)
{
if (mips_abi_regsize (gdbarch) == 8)
return mips64_linux_register_addr (gdbarch, regno, store_p);
@ -414,8 +445,8 @@ mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p)
return mips_linux_register_addr (gdbarch, regno, store_p);
}
static const struct target_desc *
mips_linux_read_description (struct target_ops *ops)
const struct target_desc *
mips_linux_nat_target::read_description ()
{
static int have_dsp = -1;
@ -499,10 +530,9 @@ mips_show_dr (const char *func, CORE_ADDR addr,
/* Target to_can_use_hw_breakpoint implementation. Return 1 if we can
handle the specified watch type. */
static int
mips_linux_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type,
int cnt, int ot)
int
mips_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
int cnt, int ot)
{
int i;
uint32_t wanted_mask, irw_mask;
@ -542,8 +572,8 @@ mips_linux_can_use_hw_breakpoint (struct target_ops *self,
stopped by watchpoint. The watchhi R and W bits indicate the watch
register triggered. */
static int
mips_linux_stopped_by_watchpoint (struct target_ops *ops)
int
mips_linux_nat_target::stopped_by_watchpoint ()
{
int n;
int num_valid;
@ -566,8 +596,8 @@ mips_linux_stopped_by_watchpoint (struct target_ops *ops)
where the watch triggered (if known). Return 1 if the address was
known. */
static int
mips_linux_stopped_data_address (struct target_ops *t, CORE_ADDR *paddr)
int
mips_linux_nat_target::stopped_data_address (CORE_ADDR *paddr)
{
/* On mips we don't know the low order 3 bits of the data address,
so we must return false. */
@ -577,9 +607,8 @@ mips_linux_stopped_data_address (struct target_ops *t, CORE_ADDR *paddr)
/* Target to_region_ok_for_hw_watchpoint implementation. Return 1 if
the specified region can be covered by the watch registers. */
static int
mips_linux_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len)
int
mips_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
struct pt_watch_regs dummy_regs;
int i;
@ -633,11 +662,10 @@ mips_linux_new_thread (struct lwp_info *lp)
/* Target to_insert_watchpoint implementation. Try to insert a new
watch. Return zero on success. */
static int
mips_linux_insert_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
mips_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
struct pt_watch_regs regs;
struct mips_watchpoint *new_watch;
@ -687,11 +715,10 @@ mips_linux_insert_watchpoint (struct target_ops *self,
/* Target to_remove_watchpoint implementation. Try to remove a watch.
Return zero on success. */
static int
mips_linux_remove_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
mips_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
int retval;
int deleted_one;
@ -736,8 +763,8 @@ mips_linux_remove_watchpoint (struct target_ops *self,
/* Target to_close implementation. Free any watches and call the
super implementation. */
static void
mips_linux_close (struct target_ops *self)
void
mips_linux_nat_target::close ()
{
struct mips_watchpoint *w;
struct mips_watchpoint *nw;
@ -752,15 +779,12 @@ mips_linux_close (struct target_ops *self)
}
current_watches = NULL;
if (super_close)
super_close (self);
linux_nat_trad_target::close ();
}
void
_initialize_mips_linux_nat (void)
{
struct target_ops *t;
add_setshow_boolean_cmd ("show-debug-regs", class_maintenance,
&show_debug_regs, _("\
Set whether to show variables that mirror the mips debug registers."), _("\
@ -774,26 +798,8 @@ triggers a breakpoint or watchpoint."),
&maintenance_set_cmdlist,
&maintenance_show_cmdlist);
t = linux_trad_target (mips_linux_register_u_offset);
super_close = t->to_close;
t->to_close = mips_linux_close;
super_fetch_registers = t->to_fetch_registers;
super_store_registers = t->to_store_registers;
t->to_fetch_registers = mips64_linux_fetch_registers;
t->to_store_registers = mips64_linux_store_registers;
t->to_can_use_hw_breakpoint = mips_linux_can_use_hw_breakpoint;
t->to_remove_watchpoint = mips_linux_remove_watchpoint;
t->to_insert_watchpoint = mips_linux_insert_watchpoint;
t->to_stopped_by_watchpoint = mips_linux_stopped_by_watchpoint;
t->to_stopped_data_address = mips_linux_stopped_data_address;
t->to_region_ok_for_hw_watchpoint = mips_linux_region_ok_for_hw_watchpoint;
t->to_read_description = mips_linux_read_description;
linux_nat_add_target (t);
linux_nat_set_new_thread (t, mips_linux_new_thread);
linux_target = &the_mips_linux_nat_target;
add_target (&the_mips_linux_nat_target);
linux_nat_set_new_thread (&the_mips_linux_nat_target,
mips_linux_new_thread);
}

View File

@ -30,6 +30,14 @@
#include "mips-nbsd-tdep.h"
#include "inf-ptrace.h"
class mips_nbsd_nat_target final : public inf_ptrace_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static mips_nbsd_nat_target the_mips_nbsd_nat_target;
/* Determine if PT_GETREGS fetches this register. */
static int
getregs_supplies (struct gdbarch *gdbarch, int regno)
@ -38,9 +46,8 @@ getregs_supplies (struct gdbarch *gdbarch, int regno)
&& (regno) <= gdbarch_pc_regnum (gdbarch));
}
static void
mipsnbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
mips_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -69,9 +76,8 @@ mipsnbsd_fetch_inferior_registers (struct target_ops *ops,
}
}
static void
mipsnbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
mips_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
{
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -110,10 +116,5 @@ mipsnbsd_store_inferior_registers (struct target_ops *ops,
void
_initialize_mipsnbsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = mipsnbsd_fetch_inferior_registers;
t->to_store_registers = mipsnbsd_store_inferior_registers;
add_target (t);
add_target (&the_mips_nbsd_nat_target);
}

View File

@ -35,6 +35,14 @@
#define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM
#define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32
struct mips64_obsd_nat_target final : public obsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static mips64_obsd_nat_target the_mips64_obsd_nat_target;
/* Supply the general-purpose registers stored in GREGS to REGCACHE. */
static void
@ -77,9 +85,8 @@ mips64obsd_collect_gregset (const struct regcache *regcache,
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
mips64obsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
mips64_obsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct reg regs;
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -94,8 +101,7 @@ mips64obsd_fetch_inferior_registers (struct target_ops *ops,
this for all registers. */
static void
mips64obsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
mips64_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
struct reg regs;
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -112,10 +118,5 @@ mips64obsd_store_inferior_registers (struct target_ops *ops,
void
_initialize_mips64obsd_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = mips64obsd_fetch_inferior_registers;
t->to_store_registers = mips64obsd_store_inferior_registers;
obsd_add_target (t);
add_target (&the_mips64_obsd_nat_target);
}

View File

@ -25,7 +25,7 @@
the child process identified by PID. */
char *
nbsd_pid_to_exec_file (struct target_ops *self, int pid)
nbsd_nat_target::pid_to_exec_file (int pid)
{
ssize_t len;
static char buf[PATH_MAX];

View File

@ -20,9 +20,13 @@
#ifndef NBSD_NAT_H
#define NBSD_NAT_H
/* Return the name of a file that can be opened to get the symbols for
the child process identified by PID. */
#include "inf-ptrace.h"
extern char *nbsd_pid_to_exec_file (struct target_ops *self, int pid);
/* A prototype NetBSD target. */
struct nbsd_nat_target : public inf_ptrace_target
{
char *pid_to_exec_file (int pid) override;
};
#endif /* nbsd-nat.h */

View File

@ -55,23 +55,105 @@ static sighandler_t ofunc;
static procfs_run run;
/* Create the "native" and "procfs" targets. */
struct nto_procfs_target : public inf_child_target
{
void open (const char *arg, int from_tty) override;
void attach (const char *, int) override = 0;
void post_attach (int);
void detach (inferior *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void files_info () override;
int insert_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
enum remove_bp_reason) override;
int can_use_hw_breakpoint (enum bptype, int, int) override;
int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int stopped_by_watchpoint () override;
void kill () override;
void create_inferior (const char *, const std::string &,
char **, int) override;
void mourn_inferior () override;
void pass_signals (int, unsigned char *) override;
int thread_alive (ptid_t ptid) override;
void update_thread_list () override;
const char *pid_to_str (ptid_t) override;
void interrupt () override;
bool have_continuable_watchpoint ()
{ return true; }
const char *extra_thread_info (struct thread_info *) override;
char *pid_to_exec_file (int pid) override;
};
/* For "target native". */
struct nto_procfs_target_native final : public nto_procfs_target
{
/* Leave shortname as "native". */
const char *longname () override
{ return _("QNX Neutrino local process"); }
const char *doc () override
{ return _("QNX Neutrino local process (started by the \"run\" command)."); }
};
/* For "target procfs <node>". */
struct nto_procfs_target_procfs final : public nto_procfs_target
{
const char *shortname () override
{ return "procfs"; }
const char *longname () override
{ return _("QNX Neutrino local or remote process"); }
const char *doc () override
{ return _("QNX Neutrino process. target procfs <node>"); }
};
static ptid_t do_attach (ptid_t ptid);
static int procfs_can_use_hw_breakpoint (struct target_ops *self,
enum bptype, int, int);
static int procfs_insert_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond);
static int procfs_remove_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond);
static int procfs_stopped_by_watchpoint (struct target_ops *ops);
/* These two globals are only ever set in procfs_open_1, but are
referenced elsewhere. 'nto_procfs_node' is a flag used to say
whether we are local, or we should get the current node descriptor
@ -109,8 +191,8 @@ procfs_is_nto_target (bfd *abfd)
<arg>' from the (gdb) prompt. For QNX6 (nto), the only valid arg
will be a QNX node string, eg: "/net/some_node". If arg is not a
valid QNX node, we will default to local. */
static void
procfs_open_1 (struct target_ops *ops, const char *arg, int from_tty)
void
nto_procfs_target::open (const char *arg, int from_tty)
{
char *endstr;
char buffer[50];
@ -202,7 +284,7 @@ procfs_open_1 (struct target_ops *ops, const char *arg, int from_tty)
}
}
inf_child_open_target (ops, arg, from_tty);
inf_child_target::open (arg, from_tty);
printf_filtered ("Debugging using %s\n", nto_procfs_path);
}
@ -216,8 +298,8 @@ procfs_set_thread (ptid_t ptid)
}
/* Return nonzero if the thread TH is still alive. */
static int
procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
int
nto_procfs_target::thread_alive (ptid_t ptid)
{
pid_t tid;
pid_t pid;
@ -298,8 +380,8 @@ update_thread_private_data (struct thread_info *new_thread,
#endif /* _NTO_VERSION */
}
static void
procfs_update_thread_list (struct target_ops *ops)
void
nto_procfs_target::update_thread_list ()
{
procfs_status status;
pid_t pid;
@ -586,8 +668,8 @@ procfs_meminfo (const char *args, int from_tty)
}
/* Print status information about what we're accessing. */
static void
procfs_files_info (struct target_ops *ignore)
void
nto_procfs_target::files_info ()
{
struct inferior *inf = current_inferior ();
@ -599,8 +681,8 @@ procfs_files_info (struct target_ops *ignore)
/* Target to_pid_to_exec_file implementation. */
static char *
procfs_pid_to_exec_file (struct target_ops *ops, const int pid)
char *
nto_procfs_target::pid_to_exec_file (const int pid)
{
int proc_fd;
static char proc_path[PATH_MAX];
@ -625,8 +707,8 @@ procfs_pid_to_exec_file (struct target_ops *ops, const int pid)
}
/* Attach to process PID, then initialize for debugging it. */
static void
procfs_attach (struct target_ops *ops, const char *args, int from_tty)
void
nto_procfs_target::attach (const char *args, int from_tty)
{
char *exec_file;
int pid;
@ -661,8 +743,8 @@ procfs_attach (struct target_ops *ops, const char *args, int from_tty)
procfs_update_thread_list (ops);
}
static void
procfs_post_attach (struct target_ops *self, pid_t pid)
void
nto_procfs_target::post_attach (pid_t pid)
{
if (exec_bfd)
solib_create_inferior_hook (0);
@ -729,9 +811,9 @@ nto_handle_sigint (int signo)
target_interrupt ();
}
static ptid_t
procfs_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus, int options)
sptid_t
nto_procfs_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int options)
{
sigset_t set;
siginfo_t info;
@ -835,9 +917,8 @@ procfs_wait (struct target_ops *ops,
/* Read the current values of the inferior's registers, both the
general register set and floating point registers (if supported)
and update gdb's idea of their current values. */
static void
procfs_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
nto_procfs_target::fetch_registers (struct regcache *regcache, int regno)
{
union
{
@ -883,11 +964,11 @@ procfs_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
/* Target to_xfer_partial implementation. */
static enum target_xfer_status
procfs_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
enum target_xfer_status
nto_procfs_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
@ -926,9 +1007,9 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
}
/* Fallthru */
default:
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
readbuf, writebuf, offset, len,
xfered_len);
return this->beneath->xfer_partial (object, annex,
readbuf, writebuf, offset, len,
xfered_len);
}
}
@ -936,8 +1017,8 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
The program resumes execution and will no longer stop
on signals, etc. We'd better not have left any breakpoints
in the program or it'll die when it hits one. */
static void
procfs_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
nto_procfs_target::detach (inferior *inf, int from_tty)
{
int pid;
@ -970,43 +1051,41 @@ procfs_breakpoint (CORE_ADDR addr, int type, int size)
return 0;
}
static int
procfs_insert_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
nto_procfs_target::insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
bp_tgt->placed_address = bp_tgt->reqstd_address;
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
}
static int
procfs_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
int
nto_procfs_target::remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
{
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
}
static int
procfs_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
nto_procfs_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
bp_tgt->placed_address = bp_tgt->reqstd_address;
return procfs_breakpoint (bp_tgt->placed_address,
_DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
}
static int
procfs_remove_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
nto_procfs_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return procfs_breakpoint (bp_tgt->placed_address,
_DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
}
static void
procfs_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signo)
void
nto_procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
{
int signal_to_pass;
procfs_status status;
@ -1065,8 +1144,8 @@ procfs_resume (struct target_ops *ops,
}
}
static void
procfs_mourn_inferior (struct target_ops *ops)
void
nto_procfs_target::mourn_inferior ()
{
if (!ptid_equal (inferior_ptid, null_ptid))
{
@ -1138,10 +1217,10 @@ breakup_args (char *scratch, char **argv)
*argv = NULL;
}
static void
procfs_create_inferior (struct target_ops *ops, const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
void
nto_procfs_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
struct inheritance inherit;
pid_t pid;
@ -1268,14 +1347,14 @@ procfs_create_inferior (struct target_ops *ops, const char *exec_file,
solib_create_inferior_hook (0);
}
static void
procfs_interrupt (struct target_ops *self)
void
nto_procfs_target::interrupt ()
{
devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
}
static void
procfs_kill_inferior (struct target_ops *ops)
void
nto_procfs_target::kill ()
{
target_mourn_inferior (inferior_ptid);
}
@ -1313,9 +1392,8 @@ get_regset (int regset, char *buf, int bufsize, int *regsize)
return dev_set;
}
static void
procfs_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
nto_procfs_target::store_registers (struct regcache *regcache, int regno)
{
union
{
@ -1380,9 +1458,8 @@ procfs_store_registers (struct target_ops *ops,
/* Set list of signals to be handled in the target. */
static void
procfs_pass_signals (struct target_ops *self,
int numsigs, unsigned char *pass_signals)
void
nto_procfs_target::pass_signals (int numsigs, unsigned char *pass_signals)
{
int signo;
@ -1396,8 +1473,8 @@ procfs_pass_signals (struct target_ops *self,
}
}
static char *
procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
char *
nto_procfs_target::pid_to_str (ptid_t ptid)
{
static char buf[1024];
int pid, tid, n;
@ -1423,87 +1500,27 @@ procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
"target procfs <node>" wouldn't make sense as default run target, as
it needs <node>. */
static int
procfs_can_run (struct target_ops *self)
int
nto_procfs_target::can_run ()
{
return 0;
}
/* "target procfs". */
static struct target_ops nto_procfs_ops;
static nto_procfs_target_procfs nto_procfs_ops;
/* "target native". */
static struct target_ops *nto_native_ops;
/* to_open implementation for "target procfs". */
static void
procfs_open (const char *arg, int from_tty)
{
procfs_open_1 (&nto_procfs_ops, arg, from_tty);
}
/* to_open implementation for "target native". */
static void
procfs_native_open (const char *arg, int from_tty)
{
procfs_open_1 (nto_native_ops, arg, from_tty);
}
static nto_procfs_target_native nto_native_ops;
/* Create the "native" and "procfs" targets. */
static void
init_procfs_targets (void)
{
struct target_ops *t = inf_child_target ();
/* Leave to_shortname as "native". */
t->to_longname = "QNX Neutrino local process";
t->to_doc = "QNX Neutrino local process (started by the \"run\" command).";
t->to_open = procfs_native_open;
t->to_attach = procfs_attach;
t->to_post_attach = procfs_post_attach;
t->to_detach = procfs_detach;
t->to_resume = procfs_resume;
t->to_wait = procfs_wait;
t->to_fetch_registers = procfs_fetch_registers;
t->to_store_registers = procfs_store_registers;
t->to_xfer_partial = procfs_xfer_partial;
t->to_files_info = procfs_files_info;
t->to_insert_breakpoint = procfs_insert_breakpoint;
t->to_remove_breakpoint = procfs_remove_breakpoint;
t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
t->to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
t->to_remove_hw_breakpoint = procfs_remove_hw_breakpoint;
t->to_insert_watchpoint = procfs_insert_hw_watchpoint;
t->to_remove_watchpoint = procfs_remove_hw_watchpoint;
t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
t->to_kill = procfs_kill_inferior;
t->to_create_inferior = procfs_create_inferior;
t->to_mourn_inferior = procfs_mourn_inferior;
t->to_pass_signals = procfs_pass_signals;
t->to_thread_alive = procfs_thread_alive;
t->to_update_thread_list = procfs_update_thread_list;
t->to_pid_to_str = procfs_pid_to_str;
t->to_interrupt = procfs_interrupt;
t->to_have_continuable_watchpoint = 1;
t->to_extra_thread_info = nto_extra_thread_info;
t->to_pid_to_exec_file = procfs_pid_to_exec_file;
nto_native_ops = t;
/* Register "target native". This is the default run target. */
add_target (t);
add_target (&nto_native_ops);
/* Register "target procfs <node>". */
nto_procfs_ops = *t;
nto_procfs_ops.to_shortname = "procfs";
nto_procfs_ops.to_can_run = procfs_can_run;
t->to_longname = "QNX Neutrino local or remote process";
t->to_doc = "QNX Neutrino process. target procfs <node>";
t->to_open = procfs_open;
add_target (&nto_procfs_ops);
}
@ -1566,34 +1583,31 @@ procfs_hw_watchpoint (int addr, int len, enum target_hw_bp_type type)
return 0;
}
static int
procfs_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type,
int cnt, int othertype)
int
nto_procfs_target::can_use_hw_breakpoint (enum bptype type,
int cnt, int othertype)
{
return 1;
}
static int
procfs_remove_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
nto_procfs_target::remove_hw_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
return procfs_hw_watchpoint (addr, -1, type);
}
static int
procfs_insert_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
nto_procfs_target::insert_hw_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
return procfs_hw_watchpoint (addr, len, type);
}
static int
procfs_stopped_by_watchpoint (struct target_ops *ops)
int
nto_procfs_target::stopped_by_watchpoint ()
{
/* NOTE: nto_stopped_by_watchpoint will be called ONLY while we are
stopped due to a SIGTRAP. This assumes gdb works in 'all-stop' mode;

View File

@ -35,8 +35,8 @@
#ifdef PT_GET_THREAD_FIRST
static const char *
obsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
obsd_nat_target::pid_to_str (ptid_t ptid)
{
if (ptid_get_lwp (ptid) != 0)
{
@ -49,8 +49,8 @@ obsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
return normal_pid_to_str (ptid);
}
static void
obsd_update_thread_list (struct target_ops *ops)
void
obsd_nat_target::update_thread_list ()
{
pid_t pid = ptid_get_pid (inferior_ptid);
struct ptrace_thread_state pts;
@ -77,9 +77,9 @@ obsd_update_thread_list (struct target_ops *ops)
}
}
static ptid_t
obsd_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus, int options)
ptid_t
obsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int options)
{
pid_t pid;
int status, save_errno;
@ -165,22 +165,4 @@ obsd_wait (struct target_ops *ops,
return ptid;
}
void
obsd_add_target (struct target_ops *t)
{
/* Override some methods to support threads. */
t->to_pid_to_str = obsd_pid_to_str;
t->to_update_thread_list = obsd_update_thread_list;
t->to_wait = obsd_wait;
add_target (t);
}
#else
void
obsd_add_target (struct target_ops *t)
{
add_target (t);
}
#endif /* PT_GET_THREAD_FIRST */

View File

@ -20,6 +20,14 @@
#ifndef OBSD_NAT_H
#define OBSD_NAT_H
extern void obsd_add_target (struct target_ops *);
#include "inf-ptrace.h"
class obsd_nat_target : public inf_ptrace_target
{
/* Override some methods to support threads. */
const char *pid_to_str (ptid_t) override;
void update_thread_list () override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
};
#endif /* obsd-nat.h */

View File

@ -37,6 +37,14 @@
#include "inf-ptrace.h"
#include "bsd-kvm.h"
struct ppc_fbsd_nat_target final : public fbsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static ppc_fbsd_nat_target the_ppc_fbsd_nat_target;
/* Fill GDB's register array with the general-purpose register values
in *GREGSETP. */
@ -115,9 +123,8 @@ getfpregs_supplies (struct gdbarch *gdbarch, int regno)
/* Fetch register REGNO from the child process. If REGNO is -1, do it
for all registers. */
static void
ppcfbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
ppc_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
gdb_gregset_t regs;
pid_t pid = ptid_get_lwp (regcache_get_ptid (regcache));
@ -142,9 +149,8 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers. */
static void
ppcfbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
ppc_fbsd_nat_target::store_registers (struct regcache *regcache, int regno)
{
gdb_gregset_t regs;
pid_t pid = ptid_get_lwp (regcache_get_ptid (regcache));
@ -198,13 +204,7 @@ ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
void
_initialize_ppcfbsd_nat (void)
{
struct target_ops *t;
/* Add in local overrides. */
t = inf_ptrace_target ();
t->to_fetch_registers = ppcfbsd_fetch_inferior_registers;
t->to_store_registers = ppcfbsd_store_inferior_registers;
fbsd_nat_add_target (t);
add_target (&the_ppc_fbsd_nat_target);
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (ppcfbsd_supply_pcb);

View File

@ -267,6 +267,57 @@ int have_ptrace_getsetregs = 1;
them and gotten an error. */
int have_ptrace_getsetfpregs = 1;
struct ppc_linux_nat_target final : public linux_nat_target
{
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
/* Add our breakpoint/watchpoint methods. */
int can_use_hw_breakpoint (enum bptype, int, int) override;
int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
override;
int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int insert_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type)
override;
int remove_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type)
override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
int can_accel_watchpoint_condition (CORE_ADDR, int, int, struct expression *)
override;
int masked_watch_num_registers (CORE_ADDR, CORE_ADDR) override;
int ranged_break_num_registers () override;
const struct target_desc *read_description () override;
int auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
override;
};
static ppc_linux_nat_target the_ppc_linux_nat_target;
/* *INDENT-OFF* */
/* registers layout, as presented by the ptrace interface:
PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
@ -806,9 +857,8 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
/* Fetch registers from the child process. Fetch all registers if
regno == -1, otherwise fetch all general registers or all floating
point registers depending upon the value of regno. */
static void
ppc_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
ppc_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -1300,7 +1350,7 @@ ppc_linux_get_hwcap (void)
{
CORE_ADDR field;
if (target_auxv_search (&current_target, AT_HWCAP, &field))
if (target_auxv_search (target_stack, AT_HWCAP, &field))
return (unsigned long) field;
return 0;
@ -1385,9 +1435,8 @@ have_ptrace_hwdebug_interface (void)
return have_ptrace_hwdebug_interface;
}
static int
ppc_linux_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type, int cnt, int ot)
int
ppc_linux_nat_target::can_use_hw_breakpoint (enum bptype type, int cnt, int ot)
{
int total_hw_wp, total_hw_bp;
@ -1443,9 +1492,8 @@ ppc_linux_can_use_hw_breakpoint (struct target_ops *self,
return 1;
}
static int
ppc_linux_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len)
int
ppc_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
/* Handle sub-8-byte quantities. */
if (len <= 0)
@ -1603,8 +1651,8 @@ hwdebug_remove_point (struct ppc_hw_breakpoint *b, int tid)
/* Return the number of registers needed for a ranged breakpoint. */
static int
ppc_linux_ranged_break_num_registers (struct target_ops *target)
int
ppc_linux_nat_target::ranged_break_num_registers ()
{
return ((have_ptrace_hwdebug_interface ()
&& hwdebug_info.features & PPC_DEBUG_FEATURE_INSN_BP_RANGE)?
@ -1614,10 +1662,9 @@ ppc_linux_ranged_break_num_registers (struct target_ops *target)
/* Insert the hardware breakpoint described by BP_TGT. Returns 0 for
success, 1 if hardware breakpoints are not supported or -1 for failure. */
static int
ppc_linux_insert_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
ppc_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct lwp_info *lp;
struct ppc_hw_breakpoint p;
@ -1651,10 +1698,9 @@ ppc_linux_insert_hw_breakpoint (struct target_ops *self,
return 0;
}
static int
ppc_linux_remove_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
ppc_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct lwp_info *lp;
struct ppc_hw_breakpoint p;
@ -1708,9 +1754,9 @@ get_trigger_type (enum target_hw_bp_type type)
or hw_access for an access watchpoint. Returns 0 on success and throws
an error on failure. */
static int
ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
CORE_ADDR mask, enum target_hw_bp_type rw)
int
ppc_linux_nat_target::insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
target_hw_bp_type rw)
{
struct lwp_info *lp;
struct ppc_hw_breakpoint p;
@ -1736,9 +1782,9 @@ ppc_linux_insert_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
or hw_access for an access watchpoint. Returns 0 on success and throws
an error on failure. */
static int
ppc_linux_remove_mask_watchpoint (struct target_ops *ops, CORE_ADDR addr,
CORE_ADDR mask, enum target_hw_bp_type rw)
int
ppc_linux_nat_target::remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
target_hw_bp_type rw)
{
struct lwp_info *lp;
struct ppc_hw_breakpoint p;
@ -1940,10 +1986,10 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
/* Return non-zero if the target is capable of using hardware to evaluate
the condition expression, thus only triggering the watchpoint when it is
true. */
static int
ppc_linux_can_accel_watchpoint_condition (struct target_ops *self,
CORE_ADDR addr, int len, int rw,
struct expression *cond)
int
ppc_linux_nat_target::can_accel_watchpoint_condition (CORE_ADDR addr, int len,
int rw,
struct expression *cond)
{
CORE_ADDR data_value;
@ -2003,10 +2049,10 @@ create_watchpoint_request (struct ppc_hw_breakpoint *p, CORE_ADDR addr,
p->addr = (uint64_t) addr;
}
static int
ppc_linux_insert_watchpoint (struct target_ops *self, CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
ppc_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
struct lwp_info *lp;
int ret = -1;
@ -2072,10 +2118,10 @@ ppc_linux_insert_watchpoint (struct target_ops *self, CORE_ADDR addr, int len,
return ret;
}
static int
ppc_linux_remove_watchpoint (struct target_ops *self, CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
ppc_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
struct lwp_info *lp;
int ret = -1;
@ -2176,8 +2222,8 @@ ppc_linux_thread_exit (struct thread_info *tp, int silent)
xfree (t);
}
static int
ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
int
ppc_linux_nat_target::stopped_data_address (CORE_ADDR *addr_p)
{
siginfo_t siginfo;
@ -2215,17 +2261,17 @@ ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
return 1;
}
static int
ppc_linux_stopped_by_watchpoint (struct target_ops *ops)
int
ppc_linux_nat_target::stopped_by_watchpoint ()
{
CORE_ADDR addr;
return ppc_linux_stopped_data_address (ops, &addr);
return stopped_data_address (&addr);
}
static int
ppc_linux_watchpoint_addr_within_range (struct target_ops *target,
CORE_ADDR addr,
CORE_ADDR start, int length)
int
ppc_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
CORE_ADDR start,
int length)
{
int mask;
@ -2245,9 +2291,8 @@ ppc_linux_watchpoint_addr_within_range (struct target_ops *target,
/* Return the number of registers needed for a masked hardware watchpoint. */
static int
ppc_linux_masked_watch_num_registers (struct target_ops *target,
CORE_ADDR addr, CORE_ADDR mask)
int
ppc_linux_nat_target::masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
{
if (!have_ptrace_hwdebug_interface ()
|| (hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_MASK) == 0)
@ -2263,9 +2308,8 @@ ppc_linux_masked_watch_num_registers (struct target_ops *target,
return 2;
}
static void
ppc_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
ppc_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -2342,9 +2386,10 @@ ppc_linux_target_wordsize (void)
return wordsize;
}
static int
ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
int
ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep,
CORE_ADDR *valp)
{
int sizeof_auxv_field = ppc_linux_target_wordsize ();
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
@ -2365,8 +2410,8 @@ ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
return 1;
}
static const struct target_desc *
ppc_linux_read_description (struct target_ops *ops)
const struct target_desc *
ppc_linux_nat_target::read_description ()
{
int altivec = 0;
int vsx = 0;
@ -2456,38 +2501,12 @@ ppc_linux_read_description (struct target_ops *ops)
void
_initialize_ppc_linux_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Add our register access methods. */
t->to_fetch_registers = ppc_linux_fetch_inferior_registers;
t->to_store_registers = ppc_linux_store_inferior_registers;
/* Add our breakpoint/watchpoint methods. */
t->to_can_use_hw_breakpoint = ppc_linux_can_use_hw_breakpoint;
t->to_insert_hw_breakpoint = ppc_linux_insert_hw_breakpoint;
t->to_remove_hw_breakpoint = ppc_linux_remove_hw_breakpoint;
t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint;
t->to_insert_watchpoint = ppc_linux_insert_watchpoint;
t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
t->to_insert_mask_watchpoint = ppc_linux_insert_mask_watchpoint;
t->to_remove_mask_watchpoint = ppc_linux_remove_mask_watchpoint;
t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
t->to_stopped_data_address = ppc_linux_stopped_data_address;
t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
t->to_can_accel_watchpoint_condition
= ppc_linux_can_accel_watchpoint_condition;
t->to_masked_watch_num_registers = ppc_linux_masked_watch_num_registers;
t->to_ranged_break_num_registers = ppc_linux_ranged_break_num_registers;
t->to_read_description = ppc_linux_read_description;
t->to_auxv_parse = ppc_linux_auxv_parse;
linux_target = &the_ppc_linux_nat_target;
gdb::observers::thread_exit.attach (ppc_linux_thread_exit);
/* Register the target. */
linux_nat_add_target (t);
linux_nat_set_new_thread (t, ppc_linux_new_thread);
add_target (linux_target);
linux_nat_set_new_thread (linux_target, ppc_linux_new_thread);
}

View File

@ -1203,7 +1203,7 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
/* Look up cached address of thread-local variable. */
if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
{
struct target_ops *target = &current_target;
struct target_ops *target = target_stack;
TRY
{
@ -1214,9 +1214,9 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
Instead, we have cached the lm_addr value, and use that to
directly call the target's to_get_thread_local_address. */
spe_context_cache_address
= target->to_get_thread_local_address (target, inferior_ptid,
spe_context_lm_addr,
spe_context_offset);
= target->get_thread_local_address (inferior_ptid,
spe_context_lm_addr,
spe_context_offset);
spe_context_cache_ptid = inferior_ptid;
}
@ -1363,7 +1363,7 @@ ppu2spu_sniffer (const struct frame_unwind *self,
return 0;
xsnprintf (annex, sizeof annex, "%d/regs", data.id);
if (target_read (&current_target, TARGET_OBJECT_SPU, annex,
if (target_read (target_stack, TARGET_OBJECT_SPU, annex,
data.gprs, 0, sizeof data.gprs)
== sizeof data.gprs)
{

View File

@ -36,6 +36,14 @@
#include "bsd-kvm.h"
#include "inf-ptrace.h"
struct ppc_nbsd_nat_target final : public inf_ptrace_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static ppc_nbsd_nat_target the_ppc_nbsd_nat_target;
/* Returns true if PT_GETREGS fetches this register. */
static int
@ -76,9 +84,8 @@ getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
|| regnum == tdep->ppc_fpscr_regnum);
}
static void
ppcnbsd_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ppc_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -106,9 +113,8 @@ ppcnbsd_fetch_inferior_registers (struct target_ops *ops,
}
}
static void
ppcnbsd_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ppc_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
struct gdbarch *gdbarch = regcache->arch ();
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -177,14 +183,8 @@ ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
void
_initialize_ppcnbsd_nat (void)
{
struct target_ops *t;
/* Support debugging kernel virtual memory images. */
bsd_kvm_add_target (ppcnbsd_supply_pcb);
/* Add in local overrides. */
t = inf_ptrace_target ();
t->to_fetch_registers = ppcnbsd_fetch_inferior_registers;
t->to_store_registers = ppcnbsd_store_inferior_registers;
add_target (t);
add_target (&the_ppc_nbsd_nat_target);
}

View File

@ -35,6 +35,14 @@
#include "obsd-nat.h"
#include "bsd-kvm.h"
struct ppc_obsd_nat_target final : public obsd_nat_target
{
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
};
static ppc_obsd_nat_target the_ppc_obsd_nat_target;
/* OpenBSD/powerpc didn't have PT_GETFPREGS/PT_SETFPREGS until release
4.0. On older releases the floating-point registers are handled by
PT_GETREGS/PT_SETREGS, but fpscr wasn't available.. */
@ -70,9 +78,8 @@ getfpregs_supplies (struct gdbarch *gdbarch, int regnum)
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
for all registers. */
static void
ppcobsd_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ppc_obsd_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct reg regs;
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -105,9 +112,8 @@ ppcobsd_fetch_registers (struct target_ops *ops,
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
this for all registers. */
static void
ppcobsd_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ppc_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
{
struct reg regs;
pid_t pid = ptid_get_pid (regcache_get_ptid (regcache));
@ -184,13 +190,7 @@ ppcobsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
void
_initialize_ppcobsd_nat (void)
{
struct target_ops *t;
/* Add in local overrides. */
t = inf_ptrace_target ();
t->to_fetch_registers = ppcobsd_fetch_registers;
t->to_store_registers = ppcobsd_store_registers;
obsd_add_target (t);
add_target (&the_ppc_obsd_nat_target);
/* General-purpose registers. */
ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr);

View File

@ -86,69 +86,88 @@
/* This module defines the GDB target vector and its methods. */
static void procfs_attach (struct target_ops *, const char *, int);
static void procfs_detach (struct target_ops *, inferior *, int);
static void procfs_resume (struct target_ops *,
ptid_t, int, enum gdb_signal);
static void procfs_files_info (struct target_ops *);
static void procfs_fetch_registers (struct target_ops *,
struct regcache *, int);
static void procfs_store_registers (struct target_ops *,
struct regcache *, int);
static void procfs_pass_signals (struct target_ops *self,
int, unsigned char *);
static void procfs_kill_inferior (struct target_ops *ops);
static void procfs_mourn_inferior (struct target_ops *ops);
static void procfs_create_inferior (struct target_ops *, const char *,
const std::string &, char **, int);
static ptid_t procfs_wait (struct target_ops *,
ptid_t, struct target_waitstatus *, int);
static enum target_xfer_status procfs_xfer_memory (gdb_byte *,
const gdb_byte *,
ULONGEST, ULONGEST,
ULONGEST *);
static target_xfer_partial_ftype procfs_xfer_partial;
static int procfs_thread_alive (struct target_ops *ops, ptid_t);
class procfs_target final : public inf_child_target
{
public:
void create_inferior (const char *, const std::string &,
char **, int) override;
static void procfs_update_thread_list (struct target_ops *ops);
static const char *procfs_pid_to_str (struct target_ops *, ptid_t);
void kill () override;
static int proc_find_memory_regions (struct target_ops *self,
find_memory_region_ftype, void *);
void mourn_inferior () override;
static char *procfs_make_note_section (struct target_ops *self,
bfd *, int *);
void attach (const char *, int) override;
void detach (inferior *inf, int) override;
static int procfs_can_use_hw_breakpoint (struct target_ops *self,
enum bptype, int, int);
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
static void procfs_info_proc (struct target_ops *, const char *,
enum info_proc_what);
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
static int procfs_stopped_by_watchpoint (struct target_ops *);
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
static int procfs_insert_watchpoint (struct target_ops *,
CORE_ADDR, int,
enum target_hw_bp_type,
struct expression *);
void pass_signals (int, unsigned char *) override;
static int procfs_remove_watchpoint (struct target_ops *,
CORE_ADDR, int,
enum target_hw_bp_type,
struct expression *);
void files_info () override;
static int procfs_region_ok_for_hw_watchpoint (struct target_ops *,
CORE_ADDR, int);
static int procfs_stopped_data_address (struct target_ops *, CORE_ADDR *);
void update_thread_list () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
thread_control_capabilities get_thread_control_capabilities () override
{ return tc_schedlock; }
/* find_memory_regions support method for gcore */
int find_memory_regions (find_memory_region_ftype func, void *data)
override;
char *make_corefile_notes (bfd *, int *) override;
bool info_proc (const char *, enum info_proc_what) override;
#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
int auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
override;
#endif
int stopped_by_watchpoint () override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
int can_use_hw_breakpoint (enum bptype, int, int) override;
int stopped_data_address (CORE_ADDR *) override;
};
static procfs_target the_procfs_target;
#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
/* When GDB is built as 64-bit application on Solaris, the auxv data
is presented in 64-bit format. We need to provide a custom parser
to handle that. */
static int
procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
int
procfs_target::auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
gdb_byte *ptr = *readptr;
@ -171,51 +190,6 @@ procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
}
#endif
/* Create a procfs target. */
static struct target_ops *
procfs_target (void)
{
struct target_ops *t = inf_child_target ();
t->to_create_inferior = procfs_create_inferior;
t->to_kill = procfs_kill_inferior;
t->to_mourn_inferior = procfs_mourn_inferior;
t->to_attach = procfs_attach;
t->to_detach = procfs_detach;
t->to_wait = procfs_wait;
t->to_resume = procfs_resume;
t->to_fetch_registers = procfs_fetch_registers;
t->to_store_registers = procfs_store_registers;
t->to_xfer_partial = procfs_xfer_partial;
t->to_pass_signals = procfs_pass_signals;
t->to_files_info = procfs_files_info;
t->to_update_thread_list = procfs_update_thread_list;
t->to_thread_alive = procfs_thread_alive;
t->to_pid_to_str = procfs_pid_to_str;
t->to_has_thread_control = tc_schedlock;
t->to_find_memory_regions = proc_find_memory_regions;
t->to_make_corefile_notes = procfs_make_note_section;
t->to_info_proc = procfs_info_proc;
#if defined(PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
t->to_auxv_parse = procfs_auxv_parse;
#endif
t->to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
t->to_insert_watchpoint = procfs_insert_watchpoint;
t->to_remove_watchpoint = procfs_remove_watchpoint;
t->to_region_ok_for_hw_watchpoint = procfs_region_ok_for_hw_watchpoint;
t->to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
t->to_stopped_data_address = procfs_stopped_data_address;
t->to_magic = OPS_MAGIC;
return t;
}
/* =================== END, TARGET_OPS "MODULE" =================== */
/* World Unification:
@ -1912,8 +1886,8 @@ procfs_debug_inferior (procinfo *pi)
return 0;
}
static void
procfs_attach (struct target_ops *ops, const char *args, int from_tty)
void
procfs_target::attach (const char *args, int from_tty)
{
char *exec_file;
int pid;
@ -1937,12 +1911,12 @@ procfs_attach (struct target_ops *ops, const char *args, int from_tty)
fflush (stdout);
}
inferior_ptid = do_attach (pid_to_ptid (pid));
if (!target_is_pushed (ops))
push_target (ops);
if (!target_is_pushed (this))
push_target (this);
}
static void
procfs_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
procfs_target::detach (inferior *inf, int from_tty)
{
int pid = ptid_get_pid (inferior_ptid);
@ -1963,7 +1937,7 @@ procfs_detach (struct target_ops *ops, inferior *inf, int from_tty)
inferior_ptid = null_ptid;
detach_inferior (pid);
inf_child_maybe_unpush_target (ops);
maybe_unpush_target ();
}
static ptid_t
@ -2092,9 +2066,8 @@ do_detach ()
registers. So we cache the results, and mark the cache invalid
when the process is resumed. */
static void
procfs_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
procfs_target::fetch_registers (struct regcache *regcache, int regnum)
{
gdb_gregset_t *gregs;
procinfo *pi;
@ -2142,9 +2115,8 @@ procfs_fetch_registers (struct target_ops *ops,
FIXME: is that a really bad idea? Have to think about cases where
writing one register might affect the value of others, etc. */
static void
procfs_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
procfs_target::store_registers (struct regcache *regcache, int regnum)
{
gdb_gregset_t *gregs;
procinfo *pi;
@ -2228,9 +2200,9 @@ syscall_is_lwp_create (procinfo *pi, int scall)
Returns the id of process (and possibly thread) that incurred the
event. Event codes are returned through a pointer parameter. */
static ptid_t
procfs_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
procfs_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
/* First cut: loosely based on original version 2.1. */
procinfo *pi;
@ -2271,7 +2243,7 @@ wait_again:
int wait_retval;
/* /proc file not found; presumably child has terminated. */
wait_retval = wait (&wstat); /* "wait" for the child's exit. */
wait_retval = ::wait (&wstat); /* "wait" for the child's exit. */
/* Wrong child? */
if (wait_retval != ptid_get_pid (inferior_ptid))
@ -2364,7 +2336,7 @@ wait_again:
}
else
{
int temp = wait (&wstat);
int temp = ::wait (&wstat);
/* FIXME: shouldn't I make sure I get the right
event from the right process? If (for
@ -2594,11 +2566,11 @@ wait_again:
/* Perform a partial transfer to/from the specified object. For
memory transfers, fall back to the old memory xfer functions. */
static enum target_xfer_status
procfs_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
enum target_xfer_status
procfs_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
switch (object)
{
@ -2606,13 +2578,13 @@ procfs_xfer_partial (struct target_ops *ops, enum target_object object,
return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
case TARGET_OBJECT_AUXV:
return memory_xfer_auxv (ops, object, annex, readbuf, writebuf,
return memory_xfer_auxv (this, object, annex, readbuf, writebuf,
offset, len, xfered_len);
default:
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
readbuf, writebuf, offset, len,
xfered_len);
return this->beneath->xfer_partial (object, annex,
readbuf, writebuf, offset, len,
xfered_len);
}
}
@ -2741,9 +2713,8 @@ make_signal_thread_runnable (procinfo *process, procinfo *pi, void *ptr)
allow any child thread to run; if non-zero, then allow only the
indicated thread to run. (not implemented yet). */
static void
procfs_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal signo)
void
procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
{
procinfo *pi, *thread;
int native_signo;
@ -2821,9 +2792,8 @@ procfs_resume (struct target_ops *ops,
/* Set up to trace signals in the child process. */
static void
procfs_pass_signals (struct target_ops *self,
int numsigs, unsigned char *pass_signals)
void
procfs_target::pass_signals (int numsigs, unsigned char *pass_signals)
{
sigset_t signals;
procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
@ -2844,8 +2814,8 @@ procfs_pass_signals (struct target_ops *self,
/* Print status information about the child process. */
static void
procfs_files_info (struct target_ops *ignore)
void
procfs_target::files_info ()
{
struct inferior *inf = current_inferior ();
@ -2887,8 +2857,8 @@ unconditionally_kill_inferior (procinfo *pi)
/* We're done debugging it, and we want it to go away. Then we want
GDB to forget all about it. */
static void
procfs_kill_inferior (struct target_ops *ops)
void
procfs_target::kill ()
{
if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */
{
@ -2903,8 +2873,8 @@ procfs_kill_inferior (struct target_ops *ops)
/* Forget we ever debugged this thing! */
static void
procfs_mourn_inferior (struct target_ops *ops)
void
procfs_target::mourn_inferior ()
{
procinfo *pi;
@ -2918,7 +2888,7 @@ procfs_mourn_inferior (struct target_ops *ops)
generic_mourn_inferior ();
inf_child_maybe_unpush_target (ops);
maybe_unpush_target ();
}
/* When GDB forks to create a runnable inferior process, this function
@ -3081,9 +3051,10 @@ procfs_set_exec_trap (void)
abstracted out and shared with other unix targets such as
inf-ptrace? */
static void
procfs_create_inferior (struct target_ops *ops, const char *exec_file,
const std::string &allargs, char **env, int from_tty)
void
procfs_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
char *shell_file = getenv ("SHELL");
char *tryname;
@ -3165,7 +3136,7 @@ procfs_create_inferior (struct target_ops *ops, const char *exec_file,
pid shouldn't change. */
add_thread_silent (pid_to_ptid (pid));
procfs_init_inferior (ops, pid);
procfs_init_inferior (this, pid);
}
/* An observer for the "inferior_created" event. */
@ -3191,8 +3162,8 @@ procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
/* Query all the threads that the target knows about, and give them
back to GDB to add to its list. */
static void
procfs_update_thread_list (struct target_ops *ops)
void
procfs_target::update_thread_list ()
{
procinfo *pi;
@ -3208,8 +3179,8 @@ procfs_update_thread_list (struct target_ops *ops)
really seem to be doing his job. Got to investigate how to tell
when a thread is really gone. */
static int
procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
int
procfs_target::thread_alive (ptid_t ptid)
{
int proc, thread;
procinfo *pi;
@ -3235,8 +3206,8 @@ procfs_thread_alive (struct target_ops *ops, ptid_t ptid)
/* Convert PTID to a string. Returns the string in a static
buffer. */
static const char *
procfs_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
procfs_target::pid_to_str (ptid_t ptid)
{
static char buf[80];
@ -3306,10 +3277,8 @@ procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag,
procfs.c targets due to the fact that some of them still define
target_can_use_hardware_watchpoint. */
static int
procfs_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type,
int cnt, int othertype)
int
procfs_target::can_use_hw_breakpoint (enum bptype type, int cnt, int othertype)
{
/* Due to the way that proc_set_watchpoint() is implemented, host
and target pointers must be of the same size. If they are not,
@ -3332,8 +3301,8 @@ procfs_can_use_hw_breakpoint (struct target_ops *self,
/* Returns non-zero if process is stopped on a hardware watchpoint
fault, else returns zero. */
static int
procfs_stopped_by_watchpoint (struct target_ops *ops)
int
procfs_target::stopped_by_watchpoint ()
{
procinfo *pi;
@ -3356,8 +3325,8 @@ procfs_stopped_by_watchpoint (struct target_ops *ops)
procfs_stopped_by_watchpoint returned 1, thus no further checks are
done. The function also assumes that ADDR is not NULL. */
static int
procfs_stopped_data_address (struct target_ops *targ, CORE_ADDR *addr)
int
procfs_target::stopped_data_address (CORE_ADDR *addr)
{
procinfo *pi;
@ -3365,11 +3334,10 @@ procfs_stopped_data_address (struct target_ops *targ, CORE_ADDR *addr)
return proc_watchpoint_address (pi, addr);
}
static int
procfs_insert_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
procfs_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
if (!target_have_steppable_watchpoint
&& !gdbarch_have_nonsteppable_watchpoint (target_gdbarch ()))
@ -3389,18 +3357,16 @@ procfs_insert_watchpoint (struct target_ops *self,
}
}
static int
procfs_remove_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
int
procfs_target::remove_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0);
}
static int
procfs_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len)
int
procfs_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
{
/* The man page for proc(4) on Solaris 2.6 and up says that the
system can support "thousands" of hardware watchpoints, but gives
@ -3494,9 +3460,8 @@ find_memory_regions_callback (struct prmap *map,
Stops iterating and returns the first non-zero value returned by
the callback. */
static int
proc_find_memory_regions (struct target_ops *self,
find_memory_region_ftype func, void *data)
int
procfs_target::find_memory_regions (find_memory_region_ftype func, void *data)
{
procinfo *pi = find_procinfo_or_die (ptid_get_pid (inferior_ptid), 0);
@ -3586,9 +3551,8 @@ info_proc_mappings (procinfo *pi, int summary)
/* Implement the "info proc" command. */
static void
procfs_info_proc (struct target_ops *ops, const char *args,
enum info_proc_what what)
bool
procfs_target::info_proc (const char *args, enum info_proc_what what)
{
struct cleanup *old_chain;
procinfo *process = NULL;
@ -3673,6 +3637,8 @@ procfs_info_proc (struct target_ops *ops, const char *args,
}
do_cleanups (old_chain);
return true;
}
/* Modify the status of the system call identified by SYSCALLNUM in
@ -3773,7 +3739,7 @@ _initialize_procfs (void)
add_com ("proc-untrace-exit", no_class, proc_untrace_sysexit_cmd,
_("Cancel a trace of exits from the syscall."));
add_target (procfs_target ());
add_target (&the_procfs_target);
}
/* =================== END, GDB "MODULE" =================== */
@ -3881,8 +3847,8 @@ find_stop_signal (void)
return GDB_SIGNAL_0;
}
static char *
procfs_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
char *
procfs_target::make_corefile_notes (bfd *obfd, int *note_size)
{
struct cleanup *old_chain;
gdb_gregset_t gregs;
@ -3936,7 +3902,7 @@ procfs_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
&thread_args);
note_data = thread_args.note_data;
auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
auxv_len = target_read_alloc (target_stack, TARGET_OBJECT_AUXV,
NULL, &auxv);
if (auxv_len > 0)
{

View File

@ -60,9 +60,6 @@
/* If non-null, ravenscar task support is enabled. */
static int ravenscar_task_support = 1;
/* This module's target-specific operations. */
static struct target_ops ravenscar_ops;
/* PTID of the last thread that received an event.
This can be useful to determine the associated task that received
the event, to make it the current task. */
@ -76,20 +73,62 @@ static const char first_task_name[] = "system__tasking__debug__first_task";
static const char ravenscar_runtime_initializer[] =
"system__bb__threads__initialize";
static void ravenscar_update_thread_list (struct target_ops *ops);
struct ravenscar_thread_target final : public target_ops
{
ravenscar_thread_target ()
{ to_stratum = thread_stratum; }
const char *shortname () override
{ return "ravenscar"; }
const char *longname () override
{ return _("Ravenscar tasks."); }
const char *doc () override
{ return _("Ravenscar tasks support."); }
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
void prepare_to_store (struct regcache *) override;
int stopped_by_sw_breakpoint () override;
int stopped_by_hw_breakpoint () override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int thread_alive (ptid_t ptid) override;
int core_of_thread (ptid_t ptid) override;
void update_thread_list () override;
const char *extra_thread_info (struct thread_info *) override;
const char *pid_to_str (ptid_t) override;
ptid_t get_ada_task_ptid (long lwp, long thread) override;
void mourn_inferior () override;
int has_all_memory () override { return default_child_has_all_memory (); }
int has_memory () override { return default_child_has_memory (); }
int has_stack () override { return default_child_has_stack (); }
int has_registers () override { return default_child_has_registers (); }
int has_execution (ptid_t ptid) override
{ return default_child_has_execution (ptid); }
};
/* This module's target-specific operations. */
static ravenscar_thread_target ravenscar_ops;
static ptid_t ravenscar_active_task (int cpu);
static const char *ravenscar_extra_thread_info (struct target_ops *self,
struct thread_info *tp);
static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
static void ravenscar_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum);
static void ravenscar_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum);
static void ravenscar_prepare_to_store (struct target_ops *self,
struct regcache *regcache);
static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal siggnal);
static void ravenscar_mourn_inferior (struct target_ops *ops);
static void ravenscar_update_inferior_ptid (void);
static int has_ravenscar_runtime (void);
static int ravenscar_runtime_initialized (void);
@ -281,26 +320,25 @@ get_running_thread_id (int cpu)
return extract_typed_address (buf, builtin_type_void_data_ptr);
}
static void
ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal siggnal)
void
ravenscar_thread_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
inferior_ptid = base_ptid;
beneath->to_resume (beneath, base_ptid, step, siggnal);
beneath->resume (base_ptid, step, siggnal);
}
static ptid_t
ravenscar_wait (struct target_ops *ops, ptid_t ptid,
struct target_waitstatus *status,
int options)
ptid_t
ravenscar_thread_target::wait (ptid_t ptid,
struct target_waitstatus *status,
int options)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
ptid_t event_ptid;
inferior_ptid = base_ptid;
event_ptid = beneath->to_wait (beneath, base_ptid, status, 0);
event_ptid = beneath->wait (base_ptid, status, 0);
/* Find any new threads that might have been created, and update
inferior_ptid to the active thread.
@ -312,7 +350,7 @@ ravenscar_wait (struct target_ops *ops, ptid_t ptid,
&& status->kind != TARGET_WAITKIND_SIGNALLED)
{
inferior_ptid = event_ptid;
ravenscar_update_thread_list (ops);
this->update_thread_list ();
ravenscar_update_inferior_ptid ();
}
return inferior_ptid;
@ -328,8 +366,8 @@ ravenscar_add_thread (struct ada_task_info *task)
add_thread (task->ptid);
}
static void
ravenscar_update_thread_list (struct target_ops *ops)
void
ravenscar_thread_target::update_thread_list ()
{
ada_build_task_list ();
@ -352,21 +390,21 @@ ravenscar_active_task (int cpu)
return ptid_build (ptid_get_pid (base_ptid), 0, tid);
}
static const char *
ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
const char *
ravenscar_thread_target::extra_thread_info (thread_info *tp)
{
return "Ravenscar task";
}
static int
ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
int
ravenscar_thread_target::thread_alive (ptid_t ptid)
{
/* Ravenscar tasks are non-terminating. */
return 1;
}
static const char *
ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
ravenscar_thread_target::pid_to_str (ptid_t ptid)
{
static char buf[30];
@ -374,11 +412,10 @@ ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
return buf;
}
static void
ravenscar_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum)
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
ptid_t ptid = regcache_get_ptid (regcache);
if (ravenscar_runtime_initialized ()
@ -392,14 +429,14 @@ ravenscar_fetch_registers (struct target_ops *ops,
arch_ops->to_fetch_registers (regcache, regnum);
}
else
beneath->to_fetch_registers (beneath, regcache, regnum);
beneath->fetch_registers (regcache, regnum);
}
static void
ravenscar_store_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
ravenscar_thread_target::store_registers (struct regcache *regcache,
int regnum)
{
struct target_ops *beneath = find_target_beneath (ops);
target_ops *beneath = find_target_beneath (this);
ptid_t ptid = regcache_get_ptid (regcache);
if (ravenscar_runtime_initialized ()
@ -410,17 +447,16 @@ ravenscar_store_registers (struct target_ops *ops,
struct ravenscar_arch_ops *arch_ops
= gdbarch_ravenscar_ops (gdbarch);
arch_ops->to_store_registers (regcache, regnum);
beneath->store_registers (regcache, regnum);
}
else
beneath->to_store_registers (beneath, regcache, regnum);
beneath->store_registers (regcache, regnum);
}
static void
ravenscar_prepare_to_store (struct target_ops *self,
struct regcache *regcache)
void
ravenscar_thread_target::prepare_to_store (struct regcache *regcache)
{
struct target_ops *beneath = find_target_beneath (self);
target_ops *beneath = find_target_beneath (this);
ptid_t ptid = regcache_get_ptid (regcache);
if (ravenscar_runtime_initialized ()
@ -431,93 +467,93 @@ ravenscar_prepare_to_store (struct target_ops *self,
struct ravenscar_arch_ops *arch_ops
= gdbarch_ravenscar_ops (gdbarch);
arch_ops->to_prepare_to_store (regcache);
beneath->prepare_to_store (regcache);
}
else
beneath->to_prepare_to_store (beneath, regcache);
beneath->prepare_to_store (regcache);
}
/* Implement the to_stopped_by_sw_breakpoint target_ops "method". */
static int
ravenscar_stopped_by_sw_breakpoint (struct target_ops *ops)
int
ravenscar_thread_target::stopped_by_sw_breakpoint ()
{
ptid_t saved_ptid = inferior_ptid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
int result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
result = beneath->to_stopped_by_sw_breakpoint (beneath);
result = beneath->stopped_by_sw_breakpoint ();
inferior_ptid = saved_ptid;
return result;
}
/* Implement the to_stopped_by_hw_breakpoint target_ops "method". */
static int
ravenscar_stopped_by_hw_breakpoint (struct target_ops *ops)
int
ravenscar_thread_target::stopped_by_hw_breakpoint ()
{
ptid_t saved_ptid = inferior_ptid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
int result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
result = beneath->to_stopped_by_hw_breakpoint (beneath);
result = beneath->stopped_by_hw_breakpoint ();
inferior_ptid = saved_ptid;
return result;
}
/* Implement the to_stopped_by_watchpoint target_ops "method". */
static int
ravenscar_stopped_by_watchpoint (struct target_ops *ops)
int
ravenscar_thread_target::stopped_by_watchpoint ()
{
ptid_t saved_ptid = inferior_ptid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
int result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
result = beneath->to_stopped_by_watchpoint (beneath);
result = beneath->stopped_by_watchpoint ();
inferior_ptid = saved_ptid;
return result;
}
/* Implement the to_stopped_data_address target_ops "method". */
static int
ravenscar_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
int
ravenscar_thread_target::stopped_data_address (CORE_ADDR *addr_p)
{
ptid_t saved_ptid = inferior_ptid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
int result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
result = beneath->to_stopped_data_address (beneath, addr_p);
result = beneath->stopped_data_address (addr_p);
inferior_ptid = saved_ptid;
return result;
}
static void
ravenscar_mourn_inferior (struct target_ops *ops)
void
ravenscar_thread_target::mourn_inferior ()
{
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
base_ptid = null_ptid;
beneath->to_mourn_inferior (beneath);
beneath->mourn_inferior ();
unpush_target (&ravenscar_ops);
}
/* Implement the to_core_of_thread target_ops "method". */
static int
ravenscar_core_of_thread (struct target_ops *ops, ptid_t ptid)
int
ravenscar_thread_target::core_of_thread (ptid_t ptid)
{
ptid_t saved_ptid = inferior_ptid;
struct target_ops *beneath = find_target_beneath (ops);
struct target_ops *beneath = find_target_beneath (this);
int result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
result = beneath->to_core_of_thread (beneath, inferior_ptid);
result = beneath->core_of_thread (inferior_ptid);
inferior_ptid = saved_ptid;
return result;
}
@ -545,45 +581,12 @@ ravenscar_inferior_created (struct target_ops *target, int from_tty)
push_target (&ravenscar_ops);
}
static ptid_t
ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
ptid_t
ravenscar_thread_target::get_ada_task_ptid (long lwp, long thread)
{
return ptid_build (ptid_get_pid (base_ptid), 0, thread);
}
static void
init_ravenscar_thread_ops (void)
{
ravenscar_ops.to_shortname = "ravenscar";
ravenscar_ops.to_longname = "Ravenscar tasks.";
ravenscar_ops.to_doc = "Ravenscar tasks support.";
ravenscar_ops.to_resume = ravenscar_resume;
ravenscar_ops.to_wait = ravenscar_wait;
ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
ravenscar_ops.to_store_registers = ravenscar_store_registers;
ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
ravenscar_ops.to_stopped_by_sw_breakpoint
= ravenscar_stopped_by_sw_breakpoint;
ravenscar_ops.to_stopped_by_hw_breakpoint
= ravenscar_stopped_by_hw_breakpoint;
ravenscar_ops.to_stopped_by_watchpoint = ravenscar_stopped_by_watchpoint;
ravenscar_ops.to_stopped_data_address = ravenscar_stopped_data_address;
ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list;
ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
ravenscar_ops.to_has_memory = default_child_has_memory;
ravenscar_ops.to_has_stack = default_child_has_stack;
ravenscar_ops.to_has_registers = default_child_has_registers;
ravenscar_ops.to_has_execution = default_child_has_execution;
ravenscar_ops.to_stratum = thread_stratum;
ravenscar_ops.to_core_of_thread = ravenscar_core_of_thread;
ravenscar_ops.to_magic = OPS_MAGIC;
}
/* Command-list for the "set/show ravenscar" prefix command. */
static struct cmd_list_element *set_ravenscar_list;
static struct cmd_list_element *show_ravenscar_list;
@ -627,15 +630,12 @@ Support for Ravenscar task/thread switching is disabled\n"));
void
_initialize_ravenscar (void)
{
init_ravenscar_thread_ops ();
base_ptid = null_ptid;
/* Notice when the inferior is created in order to push the
ravenscar ops if needed. */
gdb::observers::inferior_created.attach (ravenscar_inferior_created);
complete_target_initialization (&ravenscar_ops);
add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
_("Prefix command for changing Ravenscar-specific settings"),
&set_ravenscar_list, "set ravenscar ", 0, &setlist);

View File

@ -42,7 +42,105 @@
#include <algorithm>
/* The target_ops of record-btrace. */
static struct target_ops record_btrace_ops;
class record_btrace_target final : public target_ops
{
public:
record_btrace_target ()
{ to_stratum = record_stratum; }
const char *shortname () override
{ return "record-btrace"; }
const char *longname () override
{ return _("Branch tracing target"); }
const char *doc () override
{ return _("Collect control-flow trace and provide the execution history."); }
void open (const char *, int) override;
void close () override;
void async (int) override;
void detach (inferior *inf, int from_tty) override
{ record_detach (this, inf, from_tty); }
void disconnect (const char *, int) override;
void mourn_inferior () override
{ record_mourn_inferior (this); }
void kill () override
{ record_kill (this); }
enum record_method record_method (ptid_t ptid) override;
void stop_recording () override;
void info_record () override;
void insn_history (int size, gdb_disassembly_flags flags) override;
void insn_history_from (ULONGEST from, int size,
gdb_disassembly_flags flags) override;
void insn_history_range (ULONGEST begin, ULONGEST end,
gdb_disassembly_flags flags) override;
void call_history (int size, record_print_flags flags) override;
void call_history_from (ULONGEST begin, int size, record_print_flags flags)
override;
void call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
override;
int record_is_replaying (ptid_t ptid) override;
int record_will_replay (ptid_t ptid, int dir) override;
void record_stop_replaying () override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
int insert_breakpoint (struct gdbarch *,
struct bp_target_info *) override;
int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
enum remove_bp_reason) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
void prepare_to_store (struct regcache *) override;
const struct frame_unwind *get_unwinder () override;
const struct frame_unwind *get_tailcall_unwinder () override;
void commit_resume () override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void stop (ptid_t) override;
void update_thread_list () override;
int thread_alive (ptid_t ptid) override;
void goto_record_begin () override;
void goto_record_end () override;
void goto_record (ULONGEST insn) override;
int can_execute_reverse () override;
int stopped_by_sw_breakpoint () override;
int supports_stopped_by_sw_breakpoint () override;
int stopped_by_hw_breakpoint () override;
int supports_stopped_by_hw_breakpoint () override;
enum exec_direction_kind execution_direction () override;
void prepare_to_generate_core () override;
void done_generating_core () override;
};
static record_btrace_target record_btrace_ops;
/* Initialize the record-btrace target ops. */
/* Token associated with a new-thread observer enabling branch tracing
for the new thread. */
@ -274,10 +372,10 @@ private:
std::forward_list<thread_info *> m_threads;
};
/* The to_open method of target record-btrace. */
/* The open method of target record-btrace. */
static void
record_btrace_open (const char *args, int from_tty)
void
record_btrace_target::open (const char *args, int from_tty)
{
/* If we fail to enable btrace for one thread, disable it for the threads for
which it was successfully enabled. */
@ -304,10 +402,10 @@ record_btrace_open (const char *args, int from_tty)
btrace_disable.discard ();
}
/* The to_stop_recording method of target record-btrace. */
/* The stop_recording method of target record-btrace. */
static void
record_btrace_stop_recording (struct target_ops *self)
void
record_btrace_target::stop_recording ()
{
struct thread_info *tp;
@ -320,25 +418,25 @@ record_btrace_stop_recording (struct target_ops *self)
btrace_disable (tp);
}
/* The to_disconnect method of target record-btrace. */
/* The disconnect method of target record-btrace. */
static void
record_btrace_disconnect (struct target_ops *self, const char *args,
int from_tty)
void
record_btrace_target::disconnect (const char *args,
int from_tty)
{
struct target_ops *beneath = self->beneath;
struct target_ops *beneath = this->beneath;
/* Do not stop recording, just clean up GDB side. */
unpush_target (self);
unpush_target (this);
/* Forward disconnect. */
beneath->to_disconnect (beneath, args, from_tty);
beneath->disconnect (args, from_tty);
}
/* The to_close method of target record-btrace. */
/* The close method of target record-btrace. */
static void
record_btrace_close (struct target_ops *self)
void
record_btrace_target::close ()
{
struct thread_info *tp;
@ -355,17 +453,17 @@ record_btrace_close (struct target_ops *self)
btrace_teardown (tp);
}
/* The to_async method of target record-btrace. */
/* The async method of target record-btrace. */
static void
record_btrace_async (struct target_ops *ops, int enable)
void
record_btrace_target::async (int enable)
{
if (enable)
mark_async_event_handler (record_btrace_async_inferior_event_handler);
else
clear_async_event_handler (record_btrace_async_inferior_event_handler);
ops->beneath->to_async (ops->beneath, enable);
this->beneath->async (enable);
}
/* Adjusts the size and returns a human readable size suffix. */
@ -453,10 +551,10 @@ record_btrace_print_conf (const struct btrace_config *conf)
internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
}
/* The to_info_record method of target record-btrace. */
/* The info_record method of target record-btrace. */
static void
record_btrace_info (struct target_ops *self)
void
record_btrace_target::info_record ()
{
struct btrace_thread_info *btinfo;
const struct btrace_config *conf;
@ -473,7 +571,7 @@ record_btrace_info (struct target_ops *self)
btinfo = &tp->btrace;
conf = btrace_conf (btinfo);
conf = ::btrace_conf (btinfo);
if (conf != NULL)
record_btrace_print_conf (conf);
@ -762,11 +860,10 @@ btrace_insn_history (struct ui_out *uiout,
}
}
/* The to_insn_history method of target record-btrace. */
/* The insn_history method of target record-btrace. */
static void
record_btrace_insn_history (struct target_ops *self, int size,
gdb_disassembly_flags flags)
void
record_btrace_target::insn_history (int size, gdb_disassembly_flags flags)
{
struct btrace_thread_info *btinfo;
struct btrace_insn_history *history;
@ -846,12 +943,11 @@ record_btrace_insn_history (struct target_ops *self, int size,
btrace_set_insn_history (btinfo, &begin, &end);
}
/* The to_insn_history_range method of target record-btrace. */
/* The insn_history_range method of target record-btrace. */
static void
record_btrace_insn_history_range (struct target_ops *self,
ULONGEST from, ULONGEST to,
gdb_disassembly_flags flags)
void
record_btrace_target::insn_history_range (ULONGEST from, ULONGEST to,
gdb_disassembly_flags flags)
{
struct btrace_thread_info *btinfo;
struct btrace_insn_iterator begin, end;
@ -895,12 +991,11 @@ record_btrace_insn_history_range (struct target_ops *self,
btrace_set_insn_history (btinfo, &begin, &end);
}
/* The to_insn_history_from method of target record-btrace. */
/* The insn_history_from method of target record-btrace. */
static void
record_btrace_insn_history_from (struct target_ops *self,
ULONGEST from, int size,
gdb_disassembly_flags flags)
void
record_btrace_target::insn_history_from (ULONGEST from, int size,
gdb_disassembly_flags flags)
{
ULONGEST begin, end, context;
@ -927,7 +1022,7 @@ record_btrace_insn_history_from (struct target_ops *self,
end = ULONGEST_MAX;
}
record_btrace_insn_history_range (self, begin, end, flags);
insn_history_range (begin, end, flags);
}
/* Print the instruction number range for a function call history line. */
@ -1115,11 +1210,10 @@ btrace_call_history (struct ui_out *uiout,
}
}
/* The to_call_history method of target record-btrace. */
/* The call_history method of target record-btrace. */
static void
record_btrace_call_history (struct target_ops *self, int size,
record_print_flags flags)
void
record_btrace_target::call_history (int size, record_print_flags flags)
{
struct btrace_thread_info *btinfo;
struct btrace_call_history *history;
@ -1202,12 +1296,11 @@ record_btrace_call_history (struct target_ops *self, int size,
btrace_set_call_history (btinfo, &begin, &end);
}
/* The to_call_history_range method of target record-btrace. */
/* The call_history_range method of target record-btrace. */
static void
record_btrace_call_history_range (struct target_ops *self,
ULONGEST from, ULONGEST to,
record_print_flags flags)
void
record_btrace_target::call_history_range (ULONGEST from, ULONGEST to,
record_print_flags flags)
{
struct btrace_thread_info *btinfo;
struct btrace_call_iterator begin, end;
@ -1251,12 +1344,11 @@ record_btrace_call_history_range (struct target_ops *self,
btrace_set_call_history (btinfo, &begin, &end);
}
/* The to_call_history_from method of target record-btrace. */
/* The call_history_from method of target record-btrace. */
static void
record_btrace_call_history_from (struct target_ops *self,
ULONGEST from, int size,
record_print_flags flags)
void
record_btrace_target::call_history_from (ULONGEST from, int size,
record_print_flags flags)
{
ULONGEST begin, end, context;
@ -1283,13 +1375,13 @@ record_btrace_call_history_from (struct target_ops *self,
end = ULONGEST_MAX;
}
record_btrace_call_history_range (self, begin, end, flags);
call_history_range ( begin, end, flags);
}
/* The to_record_method method of target record-btrace. */
/* The record_method method of target record-btrace. */
static enum record_method
record_btrace_record_method (struct target_ops *self, ptid_t ptid)
enum record_method
record_btrace_target::record_method (ptid_t ptid)
{
struct thread_info * const tp = find_thread_ptid (ptid);
@ -1302,10 +1394,10 @@ record_btrace_record_method (struct target_ops *self, ptid_t ptid)
return RECORD_METHOD_BTRACE;
}
/* The to_record_is_replaying method of target record-btrace. */
/* The record_is_replaying method of target record-btrace. */
static int
record_btrace_is_replaying (struct target_ops *self, ptid_t ptid)
int
record_btrace_target::record_is_replaying (ptid_t ptid)
{
struct thread_info *tp;
@ -1316,26 +1408,26 @@ record_btrace_is_replaying (struct target_ops *self, ptid_t ptid)
return 0;
}
/* The to_record_will_replay method of target record-btrace. */
/* The record_will_replay method of target record-btrace. */
static int
record_btrace_will_replay (struct target_ops *self, ptid_t ptid, int dir)
int
record_btrace_target::record_will_replay (ptid_t ptid, int dir)
{
return dir == EXEC_REVERSE || record_btrace_is_replaying (self, ptid);
return dir == EXEC_REVERSE || record_is_replaying (ptid);
}
/* The to_xfer_partial method of target record-btrace. */
/* The xfer_partial method of target record-btrace. */
static enum target_xfer_status
record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
record_btrace_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
/* Filter out requests that don't make sense during replay. */
if (replay_memory_access == replay_memory_access_read_only
&& !record_btrace_generating_corefile
&& record_btrace_is_replaying (ops, inferior_ptid))
&& record_is_replaying (inferior_ptid))
{
switch (object)
{
@ -1351,7 +1443,7 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
}
/* We allow reading readonly memory. */
section = target_section_by_addr (ops, offset);
section = target_section_by_addr (this, offset);
if (section != NULL)
{
/* Check if the section we found is readonly. */
@ -1372,17 +1464,15 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
}
/* Forward the request. */
ops = ops->beneath;
return ops->to_xfer_partial (ops, object, annex, readbuf, writebuf,
offset, len, xfered_len);
return this->beneath->xfer_partial (object, annex, readbuf, writebuf,
offset, len, xfered_len);
}
/* The to_insert_breakpoint method of target record-btrace. */
/* The insert_breakpoint method of target record-btrace. */
static int
record_btrace_insert_breakpoint (struct target_ops *ops,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
record_btrace_target::insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
const char *old;
int ret;
@ -1395,7 +1485,7 @@ record_btrace_insert_breakpoint (struct target_ops *ops,
ret = 0;
TRY
{
ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
ret = this->beneath->insert_breakpoint (gdbarch, bp_tgt);
}
CATCH (except, RETURN_MASK_ALL)
{
@ -1408,13 +1498,12 @@ record_btrace_insert_breakpoint (struct target_ops *ops,
return ret;
}
/* The to_remove_breakpoint method of target record-btrace. */
/* The remove_breakpoint method of target record-btrace. */
static int
record_btrace_remove_breakpoint (struct target_ops *ops,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
int
record_btrace_target::remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
{
const char *old;
int ret;
@ -1427,8 +1516,7 @@ record_btrace_remove_breakpoint (struct target_ops *ops,
ret = 0;
TRY
{
ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch, bp_tgt,
reason);
ret = this->beneath->remove_breakpoint (gdbarch, bp_tgt, reason);
}
CATCH (except, RETURN_MASK_ALL)
{
@ -1441,11 +1529,10 @@ record_btrace_remove_breakpoint (struct target_ops *ops,
return ret;
}
/* The to_fetch_registers method of target record-btrace. */
/* The fetch_registers method of target record-btrace. */
static void
record_btrace_fetch_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
{
struct btrace_insn_iterator *replay;
struct thread_info *tp;
@ -1475,45 +1562,35 @@ record_btrace_fetch_registers (struct target_ops *ops,
regcache_raw_supply (regcache, regno, &insn->pc);
}
else
{
struct target_ops *t = ops->beneath;
t->to_fetch_registers (t, regcache, regno);
}
this->beneath->fetch_registers (regcache, regno);
}
/* The to_store_registers method of target record-btrace. */
/* The store_registers method of target record-btrace. */
static void
record_btrace_store_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
record_btrace_target::store_registers (struct regcache *regcache, int regno)
{
struct target_ops *t;
if (!record_btrace_generating_corefile
&& record_btrace_is_replaying (ops, regcache_get_ptid (regcache)))
&& record_is_replaying (regcache_get_ptid (regcache)))
error (_("Cannot write registers while replaying."));
gdb_assert (may_write_registers != 0);
t = ops->beneath;
t->to_store_registers (t, regcache, regno);
this->beneath->store_registers (regcache, regno);
}
/* The to_prepare_to_store method of target record-btrace. */
/* The prepare_to_store method of target record-btrace. */
static void
record_btrace_prepare_to_store (struct target_ops *ops,
struct regcache *regcache)
void
record_btrace_target::prepare_to_store (struct regcache *regcache)
{
struct target_ops *t;
if (!record_btrace_generating_corefile
&& record_btrace_is_replaying (ops, regcache_get_ptid (regcache)))
&& record_is_replaying (regcache_get_ptid (regcache)))
return;
t = ops->beneath;
t->to_prepare_to_store (t, regcache);
this->beneath->prepare_to_store (regcache);
}
/* The branch trace frame cache. */
@ -1829,18 +1906,18 @@ const struct frame_unwind record_btrace_tailcall_frame_unwind =
record_btrace_frame_dealloc_cache
};
/* Implement the to_get_unwinder method. */
/* Implement the get_unwinder method. */
static const struct frame_unwind *
record_btrace_to_get_unwinder (struct target_ops *self)
const struct frame_unwind *
record_btrace_target::get_unwinder ()
{
return &record_btrace_frame_unwind;
}
/* Implement the to_get_tailcall_unwinder method. */
/* Implement the get_tailcall_unwinder method. */
static const struct frame_unwind *
record_btrace_to_get_tailcall_unwinder (struct target_ops *self)
const struct frame_unwind *
record_btrace_target::get_tailcall_unwinder ()
{
return &record_btrace_tailcall_frame_unwind;
}
@ -1909,7 +1986,7 @@ get_thread_current_frame (struct thread_info *tp)
We are not actually running, yet. We just started a reverse execution
command or a record goto command.
For the latter, EXECUTING is false and this has no effect.
For the former, EXECUTING is true and we're in to_wait, about to
For the former, EXECUTING is true and we're in wait, about to
move the thread. Since we need to recompute the stack, we temporarily
set EXECUTING to flase. */
executing = is_executing (inferior_ptid);
@ -2059,40 +2136,38 @@ record_btrace_stop_replaying_at_end (struct thread_info *tp)
record_btrace_stop_replaying (tp);
}
/* The to_resume method of target record-btrace. */
/* The resume method of target record-btrace. */
static void
record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal signal)
void
record_btrace_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
{
struct thread_info *tp;
enum btrace_thread_flag flag, cflag;
DEBUG ("resume %s: %s%s", target_pid_to_str (ptid),
execution_direction == EXEC_REVERSE ? "reverse-" : "",
::execution_direction == EXEC_REVERSE ? "reverse-" : "",
step ? "step" : "cont");
/* Store the execution direction of the last resume.
If there is more than one to_resume call, we have to rely on infrun
If there is more than one resume call, we have to rely on infrun
to not change the execution direction in-between. */
record_btrace_resume_exec_dir = execution_direction;
record_btrace_resume_exec_dir = ::execution_direction;
/* As long as we're not replaying, just forward the request.
For non-stop targets this means that no thread is replaying. In order to
make progress, we may need to explicitly move replaying threads to the end
of their execution history. */
if ((execution_direction != EXEC_REVERSE)
&& !record_btrace_is_replaying (ops, minus_one_ptid))
if ((::execution_direction != EXEC_REVERSE)
&& !record_is_replaying (minus_one_ptid))
{
ops = ops->beneath;
ops->to_resume (ops, ptid, step, signal);
this->beneath->resume (ptid, step, signal);
return;
}
/* Compute the btrace thread flag for the requested move. */
if (execution_direction == EXEC_REVERSE)
if (::execution_direction == EXEC_REVERSE)
{
flag = step == 0 ? BTHR_RCONT : BTHR_RSTEP;
cflag = BTHR_RCONT;
@ -2135,14 +2210,14 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
}
}
/* The to_commit_resume method of target record-btrace. */
/* The commit_resume method of target record-btrace. */
static void
record_btrace_commit_resume (struct target_ops *ops)
void
record_btrace_target::commit_resume ()
{
if ((execution_direction != EXEC_REVERSE)
&& !record_btrace_is_replaying (ops, minus_one_ptid))
ops->beneath->to_commit_resume (ops->beneath);
if ((::execution_direction != EXEC_REVERSE)
&& !record_is_replaying (minus_one_ptid))
beneath->commit_resume ();
}
/* Cancel resuming TP. */
@ -2437,7 +2512,7 @@ record_btrace_step_thread (struct thread_info *tp)
return btrace_step_again ();
}
/* We keep threads moving at the end of their execution history. The to_wait
/* We keep threads moving at the end of their execution history. The wait
method will stop the thread for whom the event is reported. */
if (status.kind == TARGET_WAITKIND_NO_HISTORY)
btinfo->flags |= flags;
@ -2472,11 +2547,11 @@ record_btrace_maybe_mark_async_event
mark_async_event_handler (record_btrace_async_inferior_event_handler);
}
/* The to_wait method of target record-btrace. */
/* The wait method of target record-btrace. */
static ptid_t
record_btrace_wait (struct target_ops *ops, ptid_t ptid,
struct target_waitstatus *status, int options)
ptid_t
record_btrace_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
std::vector<thread_info *> moving;
std::vector<thread_info *> no_history;
@ -2484,11 +2559,10 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid), options);
/* As long as we're not replaying, just forward the request. */
if ((execution_direction != EXEC_REVERSE)
&& !record_btrace_is_replaying (ops, minus_one_ptid))
if ((::execution_direction != EXEC_REVERSE)
&& !record_is_replaying (minus_one_ptid))
{
ops = ops->beneath;
return ops->to_wait (ops, ptid, status, options);
return this->beneath->wait (ptid, status, options);
}
/* Keep a work list of moving threads. */
@ -2606,19 +2680,18 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
return eventing->ptid;
}
/* The to_stop method of target record-btrace. */
/* The stop method of target record-btrace. */
static void
record_btrace_stop (struct target_ops *ops, ptid_t ptid)
void
record_btrace_target::stop (ptid_t ptid)
{
DEBUG ("stop %s", target_pid_to_str (ptid));
/* As long as we're not replaying, just forward the request. */
if ((execution_direction != EXEC_REVERSE)
&& !record_btrace_is_replaying (ops, minus_one_ptid))
if ((::execution_direction != EXEC_REVERSE)
&& !record_is_replaying (minus_one_ptid))
{
ops = ops->beneath;
ops->to_stop (ops, ptid);
this->beneath->stop (ptid);
}
else
{
@ -2633,94 +2706,92 @@ record_btrace_stop (struct target_ops *ops, ptid_t ptid)
}
}
/* The to_can_execute_reverse method of target record-btrace. */
/* The can_execute_reverse method of target record-btrace. */
static int
record_btrace_can_execute_reverse (struct target_ops *self)
int
record_btrace_target::can_execute_reverse ()
{
return 1;
}
/* The to_stopped_by_sw_breakpoint method of target record-btrace. */
/* The stopped_by_sw_breakpoint method of target record-btrace. */
static int
record_btrace_stopped_by_sw_breakpoint (struct target_ops *ops)
int
record_btrace_target::stopped_by_sw_breakpoint ()
{
if (record_btrace_is_replaying (ops, minus_one_ptid))
if (record_is_replaying (minus_one_ptid))
{
struct thread_info *tp = inferior_thread ();
return tp->btrace.stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
}
return ops->beneath->to_stopped_by_sw_breakpoint (ops->beneath);
return this->beneath->stopped_by_sw_breakpoint ();
}
/* The to_supports_stopped_by_sw_breakpoint method of target
/* The supports_stopped_by_sw_breakpoint method of target
record-btrace. */
static int
record_btrace_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
int
record_btrace_target::supports_stopped_by_sw_breakpoint ()
{
if (record_btrace_is_replaying (ops, minus_one_ptid))
if (record_is_replaying (minus_one_ptid))
return 1;
return ops->beneath->to_supports_stopped_by_sw_breakpoint (ops->beneath);
return this->beneath->supports_stopped_by_sw_breakpoint ();
}
/* The to_stopped_by_sw_breakpoint method of target record-btrace. */
/* The stopped_by_sw_breakpoint method of target record-btrace. */
static int
record_btrace_stopped_by_hw_breakpoint (struct target_ops *ops)
int
record_btrace_target::stopped_by_hw_breakpoint ()
{
if (record_btrace_is_replaying (ops, minus_one_ptid))
if (record_is_replaying (minus_one_ptid))
{
struct thread_info *tp = inferior_thread ();
return tp->btrace.stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
}
return ops->beneath->to_stopped_by_hw_breakpoint (ops->beneath);
return this->beneath->stopped_by_hw_breakpoint ();
}
/* The to_supports_stopped_by_hw_breakpoint method of target
/* The supports_stopped_by_hw_breakpoint method of target
record-btrace. */
static int
record_btrace_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
int
record_btrace_target::supports_stopped_by_hw_breakpoint ()
{
if (record_btrace_is_replaying (ops, minus_one_ptid))
if (record_is_replaying (minus_one_ptid))
return 1;
return ops->beneath->to_supports_stopped_by_hw_breakpoint (ops->beneath);
return this->beneath->supports_stopped_by_hw_breakpoint ();
}
/* The to_update_thread_list method of target record-btrace. */
/* The update_thread_list method of target record-btrace. */
static void
record_btrace_update_thread_list (struct target_ops *ops)
void
record_btrace_target::update_thread_list ()
{
/* We don't add or remove threads during replay. */
if (record_btrace_is_replaying (ops, minus_one_ptid))
if (record_is_replaying (minus_one_ptid))
return;
/* Forward the request. */
ops = ops->beneath;
ops->to_update_thread_list (ops);
this->beneath->update_thread_list ();
}
/* The to_thread_alive method of target record-btrace. */
/* The thread_alive method of target record-btrace. */
static int
record_btrace_thread_alive (struct target_ops *ops, ptid_t ptid)
int
record_btrace_target::thread_alive (ptid_t ptid)
{
/* We don't add or remove threads during replay. */
if (record_btrace_is_replaying (ops, minus_one_ptid))
if (record_is_replaying (minus_one_ptid))
return find_thread_ptid (ptid) != NULL;
/* Forward the request. */
ops = ops->beneath;
return ops->to_thread_alive (ops, ptid);
return this->beneath->thread_alive (ptid);
}
/* Set the replay branch trace instruction iterator. If IT is NULL, replay
@ -2754,10 +2825,10 @@ record_btrace_set_replay (struct thread_info *tp,
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
/* The to_goto_record_begin method of target record-btrace. */
/* The goto_record_begin method of target record-btrace. */
static void
record_btrace_goto_begin (struct target_ops *self)
void
record_btrace_target::goto_record_begin ()
{
struct thread_info *tp;
struct btrace_insn_iterator begin;
@ -2779,10 +2850,10 @@ record_btrace_goto_begin (struct target_ops *self)
record_btrace_set_replay (tp, &begin);
}
/* The to_goto_record_end method of target record-btrace. */
/* The goto_record_end method of target record-btrace. */
static void
record_btrace_goto_end (struct target_ops *ops)
void
record_btrace_target::goto_record_end ()
{
struct thread_info *tp;
@ -2791,10 +2862,10 @@ record_btrace_goto_end (struct target_ops *ops)
record_btrace_set_replay (tp, NULL);
}
/* The to_goto_record method of target record-btrace. */
/* The goto_record method of target record-btrace. */
static void
record_btrace_goto (struct target_ops *self, ULONGEST insn)
void
record_btrace_target::goto_record (ULONGEST insn)
{
struct thread_info *tp;
struct btrace_insn_iterator it;
@ -2818,10 +2889,10 @@ record_btrace_goto (struct target_ops *self, ULONGEST insn)
record_btrace_set_replay (tp, &it);
}
/* The to_record_stop_replaying method of target record-btrace. */
/* The record_stop_replaying method of target record-btrace. */
static void
record_btrace_stop_replaying_all (struct target_ops *self)
void
record_btrace_target::record_stop_replaying ()
{
struct thread_info *tp;
@ -2829,91 +2900,30 @@ record_btrace_stop_replaying_all (struct target_ops *self)
record_btrace_stop_replaying (tp);
}
/* The to_execution_direction target method. */
/* The execution_direction target method. */
static enum exec_direction_kind
record_btrace_execution_direction (struct target_ops *self)
enum exec_direction_kind
record_btrace_target::execution_direction ()
{
return record_btrace_resume_exec_dir;
}
/* The to_prepare_to_generate_core target method. */
/* The prepare_to_generate_core target method. */
static void
record_btrace_prepare_to_generate_core (struct target_ops *self)
void
record_btrace_target::prepare_to_generate_core ()
{
record_btrace_generating_corefile = 1;
}
/* The to_done_generating_core target method. */
/* The done_generating_core target method. */
static void
record_btrace_done_generating_core (struct target_ops *self)
void
record_btrace_target::done_generating_core ()
{
record_btrace_generating_corefile = 0;
}
/* Initialize the record-btrace target ops. */
static void
init_record_btrace_ops (void)
{
struct target_ops *ops;
ops = &record_btrace_ops;
ops->to_shortname = "record-btrace";
ops->to_longname = "Branch tracing target";
ops->to_doc = "Collect control-flow trace and provide the execution history.";
ops->to_open = record_btrace_open;
ops->to_close = record_btrace_close;
ops->to_async = record_btrace_async;
ops->to_detach = record_detach;
ops->to_disconnect = record_btrace_disconnect;
ops->to_mourn_inferior = record_mourn_inferior;
ops->to_kill = record_kill;
ops->to_stop_recording = record_btrace_stop_recording;
ops->to_info_record = record_btrace_info;
ops->to_insn_history = record_btrace_insn_history;
ops->to_insn_history_from = record_btrace_insn_history_from;
ops->to_insn_history_range = record_btrace_insn_history_range;
ops->to_call_history = record_btrace_call_history;
ops->to_call_history_from = record_btrace_call_history_from;
ops->to_call_history_range = record_btrace_call_history_range;
ops->to_record_method = record_btrace_record_method;
ops->to_record_is_replaying = record_btrace_is_replaying;
ops->to_record_will_replay = record_btrace_will_replay;
ops->to_record_stop_replaying = record_btrace_stop_replaying_all;
ops->to_xfer_partial = record_btrace_xfer_partial;
ops->to_remove_breakpoint = record_btrace_remove_breakpoint;
ops->to_insert_breakpoint = record_btrace_insert_breakpoint;
ops->to_fetch_registers = record_btrace_fetch_registers;
ops->to_store_registers = record_btrace_store_registers;
ops->to_prepare_to_store = record_btrace_prepare_to_store;
ops->to_get_unwinder = &record_btrace_to_get_unwinder;
ops->to_get_tailcall_unwinder = &record_btrace_to_get_tailcall_unwinder;
ops->to_resume = record_btrace_resume;
ops->to_commit_resume = record_btrace_commit_resume;
ops->to_wait = record_btrace_wait;
ops->to_stop = record_btrace_stop;
ops->to_update_thread_list = record_btrace_update_thread_list;
ops->to_thread_alive = record_btrace_thread_alive;
ops->to_goto_record_begin = record_btrace_goto_begin;
ops->to_goto_record_end = record_btrace_goto_end;
ops->to_goto_record = record_btrace_goto;
ops->to_can_execute_reverse = record_btrace_can_execute_reverse;
ops->to_stopped_by_sw_breakpoint = record_btrace_stopped_by_sw_breakpoint;
ops->to_supports_stopped_by_sw_breakpoint
= record_btrace_supports_stopped_by_sw_breakpoint;
ops->to_stopped_by_hw_breakpoint = record_btrace_stopped_by_hw_breakpoint;
ops->to_supports_stopped_by_hw_breakpoint
= record_btrace_supports_stopped_by_hw_breakpoint;
ops->to_execution_direction = record_btrace_execution_direction;
ops->to_prepare_to_generate_core = record_btrace_prepare_to_generate_core;
ops->to_done_generating_core = record_btrace_done_generating_core;
ops->to_stratum = record_stratum;
ops->to_magic = OPS_MAGIC;
}
/* Start recording in BTS format. */
static void
@ -3304,7 +3314,6 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
&set_record_btrace_pt_cmdlist,
&show_record_btrace_pt_cmdlist);
init_record_btrace_ops ();
add_target (&record_btrace_ops);
bfcache = htab_create_alloc (50, bfcache_hash, bfcache_eq, NULL,

View File

@ -47,7 +47,7 @@
Target record has two modes: recording, and replaying.
In record mode, we intercept the to_resume and to_wait methods.
In record mode, we intercept the resume and wait methods.
Whenever gdb resumes the target, we run the target in single step
mode, and we build up an execution log in which, for each executed
instruction, we record all changes in memory and register state.
@ -63,7 +63,7 @@
#define DEFAULT_RECORD_FULL_INSN_MAX_NUM 200000
#define RECORD_FULL_IS_REPLAY \
(record_full_list->next || execution_direction == EXEC_REVERSE)
(record_full_list->next || ::execution_direction == EXEC_REVERSE)
#define RECORD_FULL_FILE_MAGIC netorder32(0x20091016)
@ -206,9 +206,144 @@ static unsigned int record_full_insn_num = 0;
than count of insns presently in execution log). */
static ULONGEST record_full_insn_count;
/* The target_ops of process record. */
static struct target_ops record_full_ops;
static struct target_ops record_full_core_ops;
/* Base class implementing functionality common to both the
"record-full" and "record-core" targets. */
class record_full_base_target : public target_ops
{
public:
record_full_base_target ()
{ to_stratum = record_stratum; }
const char *shortname () override = 0;
const char *longname () override
{ return _("Process record and replay target"); }
const char *doc () override
{ return _("Log program while executing and replay execution from log."); }
void open (const char *, int) override;
void close () override;
void async (int) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
int stopped_by_watchpoint () override;
int stopped_data_address (CORE_ADDR *) override;
int stopped_by_sw_breakpoint () override;
int supports_stopped_by_sw_breakpoint () override;
int stopped_by_hw_breakpoint () override;
int supports_stopped_by_hw_breakpoint () override;
int can_execute_reverse () override;
/* Add bookmark target methods. */
gdb_byte *get_bookmark (const char *, int) override;
void goto_bookmark (const gdb_byte *, int) override;
enum exec_direction_kind execution_direction () override;
enum record_method record_method (ptid_t ptid) override;
void info_record () override;
void save_record (const char *filename) override;
bool supports_delete_record () override;
void delete_record () override;
int record_is_replaying (ptid_t ptid) override;
int record_will_replay (ptid_t ptid, int dir) override;
void record_stop_replaying () override;
void goto_record_begin () override;
void goto_record_end () override;
void goto_record (ULONGEST insn) override;
};
/* The "record-full" target. */
class record_full_target final : public record_full_base_target
{
public:
const char *shortname () override
{ return "record-full"; }
void commit_resume () override;
void resume (ptid_t, int, enum gdb_signal) override;
void disconnect (const char *, int) override;
void detach (inferior *, int) override;
void mourn_inferior () override;
void kill () override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
int insert_breakpoint (struct gdbarch *,
struct bp_target_info *) override;
int remove_breakpoint (struct gdbarch *,
struct bp_target_info *,
enum remove_bp_reason) override;
};
/* The "record-core" target. */
class record_full_core_target final : public record_full_base_target
{
public:
const char *shortname () override
{ return "record-core"; }
void resume (ptid_t, int, enum gdb_signal) override;
void disconnect (const char *, int) override;
void kill () override;
void fetch_registers (struct regcache *regcache, int regno) override;
void prepare_to_store (struct regcache *regcache) override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
int insert_breakpoint (struct gdbarch *,
struct bp_target_info *) override;
int remove_breakpoint (struct gdbarch *,
struct bp_target_info *,
enum remove_bp_reason) override;
int has_execution (ptid_t) override;
};
static record_full_target record_full_ops;
static record_full_core_target record_full_core_ops;
void
record_full_target::detach (inferior *inf, int from_tty)
{
record_detach (this, inf, from_tty);
}
void
record_full_target::disconnect (const char *args, int from_tty)
{
record_disconnect (this, args, from_tty);
}
void
record_full_core_target::disconnect (const char *args, int from_tty)
{
record_disconnect (this, args, from_tty);
}
void
record_full_target::mourn_inferior ()
{
record_mourn_inferior (this);
}
void
record_full_target::kill ()
{
record_kill (this);
}
/* See record-full.h. */
@ -232,8 +367,6 @@ static struct cmd_list_element *record_full_cmdlist;
static void record_full_goto_insn (struct record_full_entry *entry,
enum exec_direction_kind dir);
static void record_full_save (struct target_ops *self,
const char *recfilename);
/* Alloc and free functions for record_full_reg, record_full_mem, and
record_full_end entries. */
@ -797,7 +930,7 @@ record_full_core_open_1 (const char *name, int from_tty)
record_full_restore ();
}
/* "to_open" target method for 'live' processes. */
/* "open" target method for 'live' processes. */
static void
record_full_open_1 (const char *name, int from_tty)
@ -821,10 +954,10 @@ record_full_open_1 (const char *name, int from_tty)
static void record_full_init_record_breakpoints (void);
/* "to_open" target method. Open the process record target. */
/* "open" target method. Open the process record target. */
static void
record_full_open (const char *name, int from_tty)
void
record_full_base_target::open (const char *name, int from_tty)
{
if (record_debug)
fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n");
@ -852,10 +985,10 @@ record_full_open (const char *name, int from_tty)
gdb::observers::record_changed.notify (current_inferior (), 1, "full", NULL);
}
/* "to_close" target method. Close the process record target. */
/* "close" target method. Close the process record target. */
static void
record_full_close (struct target_ops *self)
void
record_full_base_target::close ()
{
struct record_full_core_buf_entry *entry;
@ -887,17 +1020,17 @@ record_full_close (struct target_ops *self)
delete_async_event_handler (&record_full_async_inferior_event_token);
}
/* "to_async" target method. */
/* "async" target method. */
static void
record_full_async (struct target_ops *ops, int enable)
void
record_full_base_target::async (int enable)
{
if (enable)
mark_async_event_handler (record_full_async_inferior_event_token);
else
clear_async_event_handler (record_full_async_inferior_event_token);
ops->beneath->to_async (ops->beneath, enable);
beneath->async (enable);
}
static int record_full_resume_step = 0;
@ -923,15 +1056,14 @@ static int record_full_resumed = 0;
*/
static enum exec_direction_kind record_full_execution_dir = EXEC_FORWARD;
/* "to_resume" target method. Resume the process record target. */
/* "resume" target method. Resume the process record target. */
static void
record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal signal)
void
record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal)
{
record_full_resume_step = step;
record_full_resumed = 1;
record_full_execution_dir = execution_direction;
record_full_execution_dir = ::execution_direction;
if (!RECORD_FULL_IS_REPLAY)
{
@ -963,7 +1095,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
/* Make sure the target beneath reports all signals. */
target_pass_signals (0, NULL);
ops->beneath->to_resume (ops->beneath, ptid, step, signal);
this->beneath->resume (ptid, step, signal);
}
/* We are about to start executing the inferior (or simulate it),
@ -972,18 +1104,18 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
target_async (1);
}
/* "to_commit_resume" method for process record target. */
/* "commit_resume" method for process record target. */
static void
record_full_commit_resume (struct target_ops *ops)
void
record_full_target::commit_resume ()
{
if (!RECORD_FULL_IS_REPLAY)
ops->beneath->to_commit_resume (ops->beneath);
beneath->commit_resume ();
}
static int record_full_get_sig = 0;
/* SIGINT signal handler, registered by "to_wait" method. */
/* SIGINT signal handler, registered by "wait" method. */
static void
record_full_sig_handler (int signo)
@ -1011,13 +1143,13 @@ record_full_wait_cleanups (void *ignore)
record_full_list = record_full_list->prev;
}
/* "to_wait" target method for process record target.
/* "wait" target method for process record target.
In record mode, the target is always run in singlestep mode
(even when gdb says to continue). The to_wait method intercepts
(even when gdb says to continue). The wait method intercepts
the stop events and determines which ones are to be passed on to
gdb. Most stop events are just singlestep events that gdb is not
to know about, so the to_wait method just records them and keeps
to know about, so the wait method just records them and keeps
singlestepping.
In replay mode, this function emulates the recorded execution log,
@ -1060,7 +1192,7 @@ record_full_wait_1 (struct target_ops *ops,
if (record_full_resume_step)
{
/* This is a single step. */
return ops->beneath->to_wait (ops->beneath, ptid, status, options);
return ops->beneath->wait (ptid, status, options);
}
else
{
@ -1073,7 +1205,7 @@ record_full_wait_1 (struct target_ops *ops,
{
struct thread_info *tp;
ret = ops->beneath->to_wait (ops->beneath, ptid, status, options);
ret = ops->beneath->wait (ptid, status, options);
if (status->kind == TARGET_WAITKIND_IGNORE)
{
if (record_debug)
@ -1149,9 +1281,8 @@ record_full_wait_1 (struct target_ops *ops,
"Process record: record_full_wait "
"issuing one more step in the "
"target beneath\n");
ops->beneath->to_resume (ops->beneath, ptid, step,
GDB_SIGNAL_0);
ops->beneath->to_commit_resume (ops->beneath);
ops->beneath->resume (ptid, step, GDB_SIGNAL_0);
ops->beneath->commit_resume ();
continue;
}
}
@ -1315,14 +1446,13 @@ replay_out:
return inferior_ptid;
}
static ptid_t
record_full_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status,
int options)
ptid_t
record_full_base_target::wait (ptid_t ptid, struct target_waitstatus *status,
int options)
{
ptid_t return_ptid;
return_ptid = record_full_wait_1 (ops, ptid, status, options);
return_ptid = record_full_wait_1 (this, ptid, status, options);
if (status->kind != TARGET_WAITKIND_IGNORE)
{
/* We're reporting a stop. Make sure any spurious
@ -1333,54 +1463,54 @@ record_full_wait (struct target_ops *ops,
return return_ptid;
}
static int
record_full_stopped_by_watchpoint (struct target_ops *ops)
int
record_full_base_target::stopped_by_watchpoint ()
{
if (RECORD_FULL_IS_REPLAY)
return record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
else
return ops->beneath->to_stopped_by_watchpoint (ops->beneath);
return beneath->stopped_by_watchpoint ();
}
static int
record_full_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
int
record_full_base_target::stopped_data_address (CORE_ADDR *addr_p)
{
if (RECORD_FULL_IS_REPLAY)
return 0;
else
return ops->beneath->to_stopped_data_address (ops->beneath, addr_p);
return this->beneath->stopped_data_address (addr_p);
}
/* The to_stopped_by_sw_breakpoint method of target record-full. */
/* The stopped_by_sw_breakpoint method of target record-full. */
static int
record_full_stopped_by_sw_breakpoint (struct target_ops *ops)
int
record_full_base_target::stopped_by_sw_breakpoint ()
{
return record_full_stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
}
/* The to_supports_stopped_by_sw_breakpoint method of target
/* The supports_stopped_by_sw_breakpoint method of target
record-full. */
static int
record_full_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
int
record_full_base_target::supports_stopped_by_sw_breakpoint ()
{
return 1;
}
/* The to_stopped_by_hw_breakpoint method of target record-full. */
/* The stopped_by_hw_breakpoint method of target record-full. */
static int
record_full_stopped_by_hw_breakpoint (struct target_ops *ops)
int
record_full_base_target::stopped_by_hw_breakpoint ()
{
return record_full_stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
}
/* The to_supports_stopped_by_sw_breakpoint method of target
/* The supports_stopped_by_sw_breakpoint method of target
record-full. */
static int
record_full_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
int
record_full_base_target::supports_stopped_by_hw_breakpoint ()
{
return 1;
}
@ -1432,12 +1562,10 @@ record_full_registers_change (struct regcache *regcache, int regnum)
record_full_insn_num++;
}
/* "to_store_registers" method for process record target. */
/* "store_registers" method for process record target. */
static void
record_full_store_registers (struct target_ops *ops,
struct regcache *regcache,
int regno)
void
record_full_target::store_registers (struct regcache *regcache, int regno)
{
if (!record_full_gdb_operation_disable)
{
@ -1485,19 +1613,19 @@ record_full_store_registers (struct target_ops *ops,
record_full_registers_change (regcache, regno);
}
ops->beneath->to_store_registers (ops->beneath, regcache, regno);
this->beneath->store_registers (regcache, regno);
}
/* "to_xfer_partial" method. Behavior is conditional on
/* "xfer_partial" method. Behavior is conditional on
RECORD_FULL_IS_REPLAY.
In replay mode, we cannot write memory unles we are willing to
invalidate the record/replay log from this point forward. */
static enum target_xfer_status
record_full_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
record_full_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
if (!record_full_gdb_operation_disable
&& (object == TARGET_OBJECT_MEMORY
@ -1550,9 +1678,8 @@ record_full_xfer_partial (struct target_ops *ops, enum target_object object,
record_full_insn_num++;
}
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
readbuf, writebuf, offset,
len, xfered_len);
return this->beneath->xfer_partial (object, annex, readbuf, writebuf, offset,
len, xfered_len);
}
/* This structure represents a breakpoint inserted while the record
@ -1614,10 +1741,9 @@ record_full_init_record_breakpoints (void)
insert or remove breakpoints in the real target when replaying, nor
when recording. */
static int
record_full_insert_breakpoint (struct target_ops *ops,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
record_full_target::insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
struct record_full_breakpoint *bp;
int in_target_beneath = 0;
@ -1630,12 +1756,11 @@ record_full_insert_breakpoint (struct target_ops *ops,
However, we do have to insert software single-step
breakpoints, in case the target can't hardware step. To keep
things simple, we always insert. */
int ret;
scoped_restore restore_operation_disable
= record_full_gdb_operation_disable_set ();
ret = ops->beneath->to_insert_breakpoint (ops->beneath, gdbarch, bp_tgt);
int ret = this->beneath->insert_breakpoint (gdbarch, bp_tgt);
if (ret != 0)
return ret;
@ -1666,13 +1791,12 @@ record_full_insert_breakpoint (struct target_ops *ops,
return 0;
}
/* "to_remove_breakpoint" method for process record target. */
/* "remove_breakpoint" method for process record target. */
static int
record_full_remove_breakpoint (struct target_ops *ops,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
int
record_full_target::remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
{
struct record_full_breakpoint *bp;
int ix;
@ -1687,12 +1811,11 @@ record_full_remove_breakpoint (struct target_ops *ops,
{
if (bp->in_target_beneath)
{
int ret;
scoped_restore restore_operation_disable
= record_full_gdb_operation_disable_set ();
ret = ops->beneath->to_remove_breakpoint (ops->beneath, gdbarch,
bp_tgt, reason);
int ret = this->beneath->remove_breakpoint (gdbarch, bp_tgt,
reason);
if (ret != 0)
return ret;
}
@ -1709,19 +1832,18 @@ record_full_remove_breakpoint (struct target_ops *ops,
gdb_assert_not_reached ("removing unknown breakpoint");
}
/* "to_can_execute_reverse" method for process record target. */
/* "can_execute_reverse" method for process record target. */
static int
record_full_can_execute_reverse (struct target_ops *self)
int
record_full_base_target::can_execute_reverse ()
{
return 1;
}
/* "to_get_bookmark" method for process record and prec over core. */
/* "get_bookmark" method for process record and prec over core. */
static gdb_byte *
record_full_get_bookmark (struct target_ops *self, const char *args,
int from_tty)
gdb_byte *
record_full_base_target::get_bookmark (const char *args, int from_tty)
{
char *ret = NULL;
@ -1741,11 +1863,11 @@ record_full_get_bookmark (struct target_ops *self, const char *args,
return (gdb_byte *) ret;
}
/* "to_goto_bookmark" method for process record and prec over core. */
/* "goto_bookmark" method for process record and prec over core. */
static void
record_full_goto_bookmark (struct target_ops *self,
const gdb_byte *raw_bookmark, int from_tty)
void
record_full_base_target::goto_bookmark (const gdb_byte *raw_bookmark,
int from_tty)
{
const char *bookmark = (const char *) raw_bookmark;
@ -1766,22 +1888,22 @@ record_full_goto_bookmark (struct target_ops *self,
record_goto (bookmark);
}
static enum exec_direction_kind
record_full_execution_direction (struct target_ops *self)
enum exec_direction_kind
record_full_base_target::execution_direction ()
{
return record_full_execution_dir;
}
/* The to_record_method method of target record-full. */
/* The record_method method of target record-full. */
enum record_method
record_full_record_method (struct target_ops *self, ptid_t ptid)
record_full_base_target::record_method (ptid_t ptid)
{
return RECORD_METHOD_FULL;
}
static void
record_full_info (struct target_ops *self)
void
record_full_base_target::info_record ()
{
struct record_full_entry *p;
@ -1824,26 +1946,32 @@ record_full_info (struct target_ops *self)
record_full_insn_max_num);
}
/* The "to_record_delete" target method. */
bool
record_full_base_target::supports_delete_record ()
{
return true;
}
static void
record_full_delete (struct target_ops *self)
/* The "delete_record" target method. */
void
record_full_base_target::delete_record ()
{
record_full_list_release_following (record_full_list);
}
/* The "to_record_is_replaying" target method. */
/* The "record_is_replaying" target method. */
static int
record_full_is_replaying (struct target_ops *self, ptid_t ptid)
int
record_full_base_target::record_is_replaying (ptid_t ptid)
{
return RECORD_FULL_IS_REPLAY;
}
/* The "to_record_will_replay" target method. */
/* The "record_will_replay" target method. */
static int
record_full_will_replay (struct target_ops *self, ptid_t ptid, int dir)
int
record_full_base_target::record_will_replay (ptid_t ptid, int dir)
{
/* We can currently only record when executing forwards. Should we be able
to record when executing backwards on targets that support reverse
@ -1880,10 +2008,10 @@ record_full_goto_entry (struct record_full_entry *p)
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
/* The "to_goto_record_begin" target method. */
/* The "goto_record_begin" target method. */
static void
record_full_goto_begin (struct target_ops *self)
void
record_full_base_target::goto_record_begin ()
{
struct record_full_entry *p = NULL;
@ -1894,10 +2022,10 @@ record_full_goto_begin (struct target_ops *self)
record_full_goto_entry (p);
}
/* The "to_goto_record_end" target method. */
/* The "goto_record_end" target method. */
static void
record_full_goto_end (struct target_ops *self)
void
record_full_base_target::goto_record_end ()
{
struct record_full_entry *p = NULL;
@ -1910,10 +2038,10 @@ record_full_goto_end (struct target_ops *self)
record_full_goto_entry (p);
}
/* The "to_goto_record" target method. */
/* The "goto_record" target method. */
static void
record_full_goto (struct target_ops *self, ULONGEST target_insn)
void
record_full_base_target::goto_record (ULONGEST target_insn)
{
struct record_full_entry *p = NULL;
@ -1924,73 +2052,23 @@ record_full_goto (struct target_ops *self, ULONGEST target_insn)
record_full_goto_entry (p);
}
/* The "to_record_stop_replaying" target method. */
/* The "record_stop_replaying" target method. */
static void
record_full_stop_replaying (struct target_ops *self)
void
record_full_base_target::record_stop_replaying ()
{
record_full_goto_end (self);
goto_record_end ();
}
static void
init_record_full_ops (void)
{
record_full_ops.to_shortname = "record-full";
record_full_ops.to_longname = "Process record and replay target";
record_full_ops.to_doc =
"Log program while executing and replay execution from log.";
record_full_ops.to_open = record_full_open;
record_full_ops.to_close = record_full_close;
record_full_ops.to_async = record_full_async;
record_full_ops.to_resume = record_full_resume;
record_full_ops.to_commit_resume = record_full_commit_resume;
record_full_ops.to_wait = record_full_wait;
record_full_ops.to_disconnect = record_disconnect;
record_full_ops.to_detach = record_detach;
record_full_ops.to_mourn_inferior = record_mourn_inferior;
record_full_ops.to_kill = record_kill;
record_full_ops.to_store_registers = record_full_store_registers;
record_full_ops.to_xfer_partial = record_full_xfer_partial;
record_full_ops.to_insert_breakpoint = record_full_insert_breakpoint;
record_full_ops.to_remove_breakpoint = record_full_remove_breakpoint;
record_full_ops.to_stopped_by_watchpoint = record_full_stopped_by_watchpoint;
record_full_ops.to_stopped_data_address = record_full_stopped_data_address;
record_full_ops.to_stopped_by_sw_breakpoint
= record_full_stopped_by_sw_breakpoint;
record_full_ops.to_supports_stopped_by_sw_breakpoint
= record_full_supports_stopped_by_sw_breakpoint;
record_full_ops.to_stopped_by_hw_breakpoint
= record_full_stopped_by_hw_breakpoint;
record_full_ops.to_supports_stopped_by_hw_breakpoint
= record_full_supports_stopped_by_hw_breakpoint;
record_full_ops.to_can_execute_reverse = record_full_can_execute_reverse;
record_full_ops.to_stratum = record_stratum;
/* Add bookmark target methods. */
record_full_ops.to_get_bookmark = record_full_get_bookmark;
record_full_ops.to_goto_bookmark = record_full_goto_bookmark;
record_full_ops.to_execution_direction = record_full_execution_direction;
record_full_ops.to_record_method = record_full_record_method;
record_full_ops.to_info_record = record_full_info;
record_full_ops.to_save_record = record_full_save;
record_full_ops.to_delete_record = record_full_delete;
record_full_ops.to_record_is_replaying = record_full_is_replaying;
record_full_ops.to_record_will_replay = record_full_will_replay;
record_full_ops.to_record_stop_replaying = record_full_stop_replaying;
record_full_ops.to_goto_record_begin = record_full_goto_begin;
record_full_ops.to_goto_record_end = record_full_goto_end;
record_full_ops.to_goto_record = record_full_goto;
record_full_ops.to_magic = OPS_MAGIC;
}
/* "resume" method for prec over corefile. */
/* "to_resume" method for prec over corefile. */
static void
record_full_core_resume (struct target_ops *ops, ptid_t ptid, int step,
enum gdb_signal signal)
void
record_full_core_target::resume (ptid_t ptid, int step,
enum gdb_signal signal)
{
record_full_resume_step = step;
record_full_resumed = 1;
record_full_execution_dir = execution_direction;
record_full_execution_dir = ::execution_direction;
/* We are about to start executing the inferior (or simulate it),
let's register it with the event loop. */
@ -1998,23 +2076,22 @@ record_full_core_resume (struct target_ops *ops, ptid_t ptid, int step,
target_async (1);
}
/* "to_kill" method for prec over corefile. */
/* "kill" method for prec over corefile. */
static void
record_full_core_kill (struct target_ops *ops)
void
record_full_core_target::kill ()
{
if (record_debug)
fprintf_unfiltered (gdb_stdlog, "Process record: record_full_core_kill\n");
unpush_target (&record_full_core_ops);
unpush_target (this);
}
/* "to_fetch_registers" method for prec over corefile. */
/* "fetch_registers" method for prec over corefile. */
static void
record_full_core_fetch_registers (struct target_ops *ops,
struct regcache *regcache,
int regno)
void
record_full_core_target::fetch_registers (struct regcache *regcache,
int regno)
{
if (regno < 0)
{
@ -2028,20 +2105,18 @@ record_full_core_fetch_registers (struct target_ops *ops,
regcache->raw_supply (regno, *record_full_core_regbuf);
}
/* "to_prepare_to_store" method for prec over corefile. */
/* "prepare_to_store" method for prec over corefile. */
static void
record_full_core_prepare_to_store (struct target_ops *self,
struct regcache *regcache)
void
record_full_core_target::prepare_to_store (struct regcache *regcache)
{
}
/* "to_store_registers" method for prec over corefile. */
/* "store_registers" method for prec over corefile. */
static void
record_full_core_store_registers (struct target_ops *ops,
struct regcache *regcache,
int regno)
void
record_full_core_target::store_registers (struct regcache *regcache,
int regno)
{
if (record_full_gdb_operation_disable)
record_full_core_regbuf->raw_supply (regno, *regcache);
@ -2049,14 +2124,13 @@ record_full_core_store_registers (struct target_ops *ops,
error (_("You can't do that without a process to debug."));
}
/* "to_xfer_partial" method for prec over corefile. */
/* "xfer_partial" method for prec over corefile. */
static enum target_xfer_status
record_full_core_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
record_full_core_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset,
ULONGEST len, ULONGEST *xfered_len)
{
if (object == TARGET_OBJECT_MEMORY)
{
@ -2120,11 +2194,10 @@ record_full_core_xfer_partial (struct target_ops *ops,
else
{
if (!entry)
return ops->beneath->to_xfer_partial (ops->beneath,
object, annex,
readbuf, writebuf,
offset, len,
xfered_len);
return this->beneath->xfer_partial (object, annex,
readbuf, writebuf,
offset, len,
xfered_len);
memcpy (readbuf, entry->buf + sec_offset,
(size_t) len);
@ -2141,93 +2214,38 @@ record_full_core_xfer_partial (struct target_ops *ops,
error (_("You can't do that without a process to debug."));
}
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
readbuf, writebuf, offset, len,
xfered_len);
return this->beneath->xfer_partial (object, annex,
readbuf, writebuf, offset, len,
xfered_len);
}
/* "to_insert_breakpoint" method for prec over corefile. */
/* "insert_breakpoint" method for prec over corefile. */
static int
record_full_core_insert_breakpoint (struct target_ops *ops,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
record_full_core_target::insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
return 0;
}
/* "to_remove_breakpoint" method for prec over corefile. */
/* "remove_breakpoint" method for prec over corefile. */
static int
record_full_core_remove_breakpoint (struct target_ops *ops,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
int
record_full_core_target::remove_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt,
enum remove_bp_reason reason)
{
return 0;
}
/* "to_has_execution" method for prec over corefile. */
/* "has_execution" method for prec over corefile. */
static int
record_full_core_has_execution (struct target_ops *ops, ptid_t the_ptid)
int
record_full_core_target::has_execution (ptid_t the_ptid)
{
return 1;
}
static void
init_record_full_core_ops (void)
{
record_full_core_ops.to_shortname = "record-core";
record_full_core_ops.to_longname = "Process record and replay target";
record_full_core_ops.to_doc =
"Log program while executing and replay execution from log.";
record_full_core_ops.to_open = record_full_open;
record_full_core_ops.to_close = record_full_close;
record_full_core_ops.to_async = record_full_async;
record_full_core_ops.to_resume = record_full_core_resume;
record_full_core_ops.to_wait = record_full_wait;
record_full_core_ops.to_kill = record_full_core_kill;
record_full_core_ops.to_fetch_registers = record_full_core_fetch_registers;
record_full_core_ops.to_prepare_to_store = record_full_core_prepare_to_store;
record_full_core_ops.to_store_registers = record_full_core_store_registers;
record_full_core_ops.to_xfer_partial = record_full_core_xfer_partial;
record_full_core_ops.to_insert_breakpoint
= record_full_core_insert_breakpoint;
record_full_core_ops.to_remove_breakpoint
= record_full_core_remove_breakpoint;
record_full_core_ops.to_stopped_by_watchpoint
= record_full_stopped_by_watchpoint;
record_full_core_ops.to_stopped_data_address
= record_full_stopped_data_address;
record_full_core_ops.to_stopped_by_sw_breakpoint
= record_full_stopped_by_sw_breakpoint;
record_full_core_ops.to_supports_stopped_by_sw_breakpoint
= record_full_supports_stopped_by_sw_breakpoint;
record_full_core_ops.to_stopped_by_hw_breakpoint
= record_full_stopped_by_hw_breakpoint;
record_full_core_ops.to_supports_stopped_by_hw_breakpoint
= record_full_supports_stopped_by_hw_breakpoint;
record_full_core_ops.to_can_execute_reverse
= record_full_can_execute_reverse;
record_full_core_ops.to_has_execution = record_full_core_has_execution;
record_full_core_ops.to_stratum = record_stratum;
/* Add bookmark target methods. */
record_full_core_ops.to_get_bookmark = record_full_get_bookmark;
record_full_core_ops.to_goto_bookmark = record_full_goto_bookmark;
record_full_core_ops.to_execution_direction
= record_full_execution_direction;
record_full_core_ops.to_record_method = record_full_record_method;
record_full_core_ops.to_info_record = record_full_info;
record_full_core_ops.to_delete_record = record_full_delete;
record_full_core_ops.to_record_is_replaying = record_full_is_replaying;
record_full_core_ops.to_record_will_replay = record_full_will_replay;
record_full_core_ops.to_goto_record_begin = record_full_goto_begin;
record_full_core_ops.to_goto_record_end = record_full_goto_end;
record_full_core_ops.to_goto_record = record_full_goto;
record_full_core_ops.to_magic = OPS_MAGIC;
}
/* Record log save-file format
Version 1 (never released)
@ -2501,14 +2519,14 @@ static void
cmd_record_full_restore (const char *args, int from_tty)
{
core_file_command (args, from_tty);
record_full_open (args, from_tty);
record_full_ops.open (args, from_tty);
}
/* Save the execution log to a file. We use a modified elf corefile
format, with an extra section for our data. */
static void
record_full_save (struct target_ops *self, const char *recfilename)
void
record_full_base_target::save_record (const char *recfilename)
{
struct record_full_entry *cur_record_full_list;
uint32_t magic;
@ -2790,10 +2808,8 @@ _initialize_record_full (void)
record_full_first.next = NULL;
record_full_first.type = record_full_end;
init_record_full_ops ();
add_target (&record_full_ops);
add_deprecated_target_alias (&record_full_ops, "record");
init_record_full_core_ops ();
add_target (&record_full_core_ops);
add_prefix_cmd ("full", class_obscure, cmd_record_full_start,

View File

@ -154,9 +154,9 @@ record_read_memory (struct gdbarch *gdbarch,
static void
record_stop (struct target_ops *t)
{
DEBUG ("stop %s", t->to_shortname);
DEBUG ("stop %s", t->shortname ());
t->to_stop_recording (t);
t->stop_recording ();
}
/* Unpush the record target. */
@ -164,7 +164,7 @@ record_stop (struct target_ops *t)
static void
record_unpush (struct target_ops *t)
{
DEBUG ("unpush %s", t->to_shortname);
DEBUG ("unpush %s", t->shortname ());
unpush_target (t);
}
@ -176,7 +176,7 @@ record_disconnect (struct target_ops *t, const char *args, int from_tty)
{
gdb_assert (t->to_stratum == record_stratum);
DEBUG ("disconnect %s", t->to_shortname);
DEBUG ("disconnect %s", t->shortname ());
record_stop (t);
record_unpush (t);
@ -191,7 +191,7 @@ record_detach (struct target_ops *t, inferior *inf, int from_tty)
{
gdb_assert (t->to_stratum == record_stratum);
DEBUG ("detach %s", t->to_shortname);
DEBUG ("detach %s", t->shortname ());
record_stop (t);
record_unpush (t);
@ -206,7 +206,7 @@ record_mourn_inferior (struct target_ops *t)
{
gdb_assert (t->to_stratum == record_stratum);
DEBUG ("mourn inferior %s", t->to_shortname);
DEBUG ("mourn inferior %s", t->shortname ());
/* It is safer to not stop recording. Resources will be freed when
threads are discarded. */
@ -222,7 +222,7 @@ record_kill (struct target_ops *t)
{
gdb_assert (t->to_stratum == record_stratum);
DEBUG ("kill %s", t->to_shortname);
DEBUG ("kill %s", t->shortname ());
/* It is safer to not stop recording. Resources will be freed when
threads are discarded. */
@ -346,8 +346,8 @@ info_record_command (const char *args, int from_tty)
return;
}
printf_filtered (_("Active record target: %s\n"), t->to_shortname);
t->to_info_record (t);
printf_filtered (_("Active record target: %s\n"), t->shortname ());
t->info_record ();
}
/* The "record save" command. */

View File

@ -1488,30 +1488,12 @@ current_regcache_test (void)
SELF_CHECK (regcache_access::current_regcache_size () == 2);
}
static void test_target_fetch_registers (target_ops *self, regcache *regs,
int regno);
static void test_target_store_registers (target_ops *self, regcache *regs,
int regno);
static enum target_xfer_status
test_target_xfer_partial (struct target_ops *ops,
enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len);
class target_ops_no_register : public test_target_ops
{
public:
target_ops_no_register ()
: test_target_ops {}
{
to_fetch_registers = test_target_fetch_registers;
to_store_registers = test_target_store_registers;
to_xfer_partial = test_target_xfer_partial;
to_data = this;
}
{}
void reset ()
{
@ -1520,38 +1502,42 @@ public:
xfer_partial_called = 0;
}
void fetch_registers (regcache *regs, int regno) override;
void store_registers (regcache *regs, int regno) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
unsigned int fetch_registers_called = 0;
unsigned int store_registers_called = 0;
unsigned int xfer_partial_called = 0;
};
static void
test_target_fetch_registers (target_ops *self, regcache *regs, int regno)
void
target_ops_no_register::fetch_registers (regcache *regs, int regno)
{
auto ops = static_cast<target_ops_no_register *> (self->to_data);
/* Mark register available. */
regs->raw_supply_zeroed (regno);
ops->fetch_registers_called++;
this->fetch_registers_called++;
}
static void
test_target_store_registers (target_ops *self, regcache *regs, int regno)
void
target_ops_no_register::store_registers (regcache *regs, int regno)
{
auto ops = static_cast<target_ops_no_register *> (self->to_data);
ops->store_registers_called++;
this->store_registers_called++;
}
static enum target_xfer_status
test_target_xfer_partial (struct target_ops *self, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
target_ops_no_register::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
auto ops = static_cast<target_ops_no_register *> (self->to_data);
ops->xfer_partial_called++;
this->xfer_partial_called++;
*xfered_len = len;
return TARGET_XFER_OK;
@ -1573,7 +1559,7 @@ cooked_read_test (struct gdbarch *gdbarch)
{
/* Error out if debugging something, because we're going to push the
test target, which would pop any existing target. */
if (current_target.to_stratum >= process_stratum)
if (target_stack->to_stratum >= process_stratum)
error (_("target already pushed"));
/* Create a mock environment. An inferior with a thread, with a
@ -1747,7 +1733,7 @@ cooked_write_test (struct gdbarch *gdbarch)
{
/* Error out if debugging something, because we're going to push the
test target, which would pop any existing target. */
if (current_target.to_stratum >= process_stratum)
if (target_stack->to_stratum >= process_stratum)
error (_("target already pushed"));
/* Create a mock environment. A process_stratum target pushed. */

View File

@ -68,26 +68,6 @@ static void gdb_os_evprintf_filtered (host_callback *, const char *, va_list);
static void gdb_os_error (host_callback *, const char *, ...)
ATTRIBUTE_NORETURN;
static void gdbsim_kill (struct target_ops *);
static void gdbsim_load (struct target_ops *self, const char *prog,
int fromtty);
static void gdbsim_open (const char *args, int from_tty);
static void gdbsim_close (struct target_ops *self);
static void gdbsim_detach (struct target_ops *ops, inferior *inf, int from_tty);
static void gdbsim_prepare_to_store (struct target_ops *self,
struct regcache *regcache);
static void gdbsim_files_info (struct target_ops *target);
static void gdbsim_mourn_inferior (struct target_ops *target);
static void gdbsim_interrupt (struct target_ops *self);
void simulator_command (char *args, int from_tty);
/* Naming convention:
@ -95,8 +75,72 @@ void simulator_command (char *args, int from_tty);
sim_* are the interface to the simulator (see remote-sim.h).
gdbsim_* are stuff which is internal to gdb. */
/* Forward data declarations */
extern struct target_ops gdbsim_ops;
struct gdbsim_target final
: public memory_breakpoint_target<target_ops>
{
gdbsim_target ()
{ to_stratum = process_stratum; }
const char *shortname () override
{ return "sim"; }
const char *longname () override
{ return _("simulator"); }
const char *doc () override
{ return _("Use the compiled-in simulator."); }
void open (const char *, int) override;
void close () override;
void detach (inferior *inf, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
void prepare_to_store (struct regcache *) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void files_info () override;
void kill () override;
void load (const char *, int) override;
bool can_create_inferior () override { return true; }
void create_inferior (const char *, const std::string &,
char **, int) override;
void mourn_inferior () override;
void interrupt () override;
int thread_alive (ptid_t ptid) override;
const char *pid_to_str (ptid_t) override;
int has_all_memory () override;
int has_memory () override;
int has_stack () override
{ return default_child_has_stack (); }
int has_registers () override
{ return default_child_has_registers (); }
int has_execution (ptid_t ptid) override
{ return default_child_has_execution (ptid); }
};
static struct gdbsim_target gdbsim_ops;
static const struct inferior_data *sim_inferior_data_key;
@ -422,9 +466,8 @@ one2one_register_sim_regno (struct gdbarch *gdbarch, int regnum)
return regnum;
}
static void
gdbsim_fetch_register (struct target_ops *ops,
struct regcache *regcache, int regno)
void
gdbsim_target::fetch_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
struct inferior *inf = find_inferior_ptid (regcache_get_ptid (regcache));
@ -434,7 +477,7 @@ gdbsim_fetch_register (struct target_ops *ops,
if (regno == -1)
{
for (regno = 0; regno < gdbarch_num_regs (gdbarch); regno++)
gdbsim_fetch_register (ops, regcache, regno);
fetch_registers (regcache, regno);
return;
}
@ -492,9 +535,8 @@ gdbsim_fetch_register (struct target_ops *ops,
}
static void
gdbsim_store_register (struct target_ops *ops,
struct regcache *regcache, int regno)
void
gdbsim_target::store_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
struct inferior *inf = find_inferior_ptid (regcache_get_ptid (regcache));
@ -504,7 +546,7 @@ gdbsim_store_register (struct target_ops *ops,
if (regno == -1)
{
for (regno = 0; regno < gdbarch_num_regs (gdbarch); regno++)
gdbsim_store_register (ops, regcache, regno);
store_registers (regcache, regno);
return;
}
else if (gdbarch_register_sim_regno (gdbarch, regno) >= 0)
@ -541,8 +583,8 @@ gdbsim_store_register (struct target_ops *ops,
/* Kill the running program. This may involve closing any open files
and releasing other resources acquired by the simulated program. */
static void
gdbsim_kill (struct target_ops *ops)
void
gdbsim_target::kill ()
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "gdbsim_kill\n");
@ -556,8 +598,8 @@ gdbsim_kill (struct target_ops *ops)
not only bring new code into the target process, but also to update
GDB's symbol tables to match. */
static void
gdbsim_load (struct target_ops *self, const char *args, int fromtty)
void
gdbsim_target::load (const char *args, int fromtty)
{
const char *prog;
struct sim_inferior_data *sim_data
@ -597,9 +639,10 @@ gdbsim_load (struct target_ops *self, const char *args, int fromtty)
/* This is called not only when we first attach, but also when the
user types "run" after having attached. */
static void
gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
const std::string &allargs, char **env, int from_tty)
void
gdbsim_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
@ -619,7 +662,7 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
args);
if (ptid_equal (inferior_ptid, sim_data->remote_sim_ptid))
gdbsim_kill (target);
kill ();
remove_breakpoints ();
init_wait_for_inferior ();
@ -658,8 +701,8 @@ gdbsim_create_inferior (struct target_ops *target, const char *exec_file,
Targets should supply this routine, if only to provide an error message. */
/* Called when selecting the simulator. E.g. (gdb) target sim name. */
static void
gdbsim_open (const char *args, int from_tty)
void
gdbsim_target::open (const char *args, int from_tty)
{
int len;
char *arg_buf;
@ -789,8 +832,8 @@ gdbsim_close_inferior (struct inferior *inf, void *arg)
/* Close out all files and local state before this target loses control. */
static void
gdbsim_close (struct target_ops *self)
void
gdbsim_target::close ()
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
@ -819,13 +862,13 @@ gdbsim_close (struct target_ops *self)
/* Terminate the open connection to the remote debugger.
Use this when you want to detach and do something else with your gdb. */
static void
gdbsim_detach (struct target_ops *ops, inferior *inf, int from_tty)
void
gdbsim_target::detach (inferior *inf, int from_tty)
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "gdbsim_detach\n");
unpush_target (ops); /* calls gdbsim_close to do the real work */
unpush_target (this); /* calls gdbsim_close to do the real work */
if (from_tty)
printf_filtered ("Ending simulator %s debugging\n", target_shortname);
}
@ -864,9 +907,8 @@ gdbsim_resume_inferior (struct inferior *inf, void *arg)
return 0;
}
static void
gdbsim_resume (struct target_ops *ops,
ptid_t ptid, int step, enum gdb_signal siggnal)
void
gdbsim_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
{
struct resume_data rd;
struct sim_inferior_data *sim_data
@ -919,8 +961,8 @@ gdbsim_interrupt_inferior (struct inferior *inf, void *arg)
return 0;
}
static void
gdbsim_interrupt (struct target_ops *self)
void
gdbsim_target::interrupt ()
{
iterate_over_inferiors (gdbsim_interrupt_inferior, NULL);
}
@ -946,12 +988,11 @@ gdb_os_poll_quit (host_callback *p)
static void
gdbsim_cntrl_c (int signo)
{
gdbsim_interrupt (NULL);
gdbsim_ops.interrupt ();
}
static ptid_t
gdbsim_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *status, int options)
ptid_t
gdbsim_target::wait (ptid_t ptid, struct target_waitstatus *status, int options)
{
struct sim_inferior_data *sim_data;
static sighandler_t prev_sigint;
@ -1035,8 +1076,8 @@ gdbsim_wait (struct target_ops *ops,
that registers contains all the registers from the program being
debugged. */
static void
gdbsim_prepare_to_store (struct target_ops *self, struct regcache *regcache)
void
gdbsim_target::prepare_to_store (struct regcache *regcache)
{
/* Do nothing, since we can store individual regs. */
}
@ -1056,7 +1097,7 @@ gdbsim_xfer_memory (struct target_ops *target,
/* If this target doesn't have memory yet, return 0 causing the
request to be passed to a lower target, hopefully an exec
file. */
if (!target->to_has_memory (target))
if (!target->has_memory ())
return TARGET_XFER_EOF;
if (!sim_data->program_loaded)
@ -1104,16 +1145,16 @@ gdbsim_xfer_memory (struct target_ops *target,
/* Target to_xfer_partial implementation. */
static enum target_xfer_status
gdbsim_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
enum target_xfer_status
gdbsim_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
switch (object)
{
case TARGET_OBJECT_MEMORY:
return gdbsim_xfer_memory (ops, readbuf, writebuf, offset, len,
return gdbsim_xfer_memory (this, readbuf, writebuf, offset, len,
xfered_len);
default:
@ -1121,8 +1162,8 @@ gdbsim_xfer_partial (struct target_ops *ops, enum target_object object,
}
}
static void
gdbsim_files_info (struct target_ops *target)
void
gdbsim_target::files_info ()
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NEEDED);
@ -1144,8 +1185,8 @@ gdbsim_files_info (struct target_ops *target)
/* Clear the simulator's notion of what the break points are. */
static void
gdbsim_mourn_inferior (struct target_ops *target)
void
gdbsim_target::mourn_inferior ()
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
@ -1247,8 +1288,8 @@ sim_command_completer (struct cmd_list_element *ignore,
/* Check to see if a thread is still alive. */
static int
gdbsim_thread_alive (struct target_ops *ops, ptid_t ptid)
int
gdbsim_target::thread_alive (ptid_t ptid)
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data_by_ptid (ptid, SIM_INSTANCE_NOT_NEEDED);
@ -1266,16 +1307,16 @@ gdbsim_thread_alive (struct target_ops *ops, ptid_t ptid)
/* Convert a thread ID to a string. Returns the string in a static
buffer. */
static const char *
gdbsim_pid_to_str (struct target_ops *ops, ptid_t ptid)
const char *
gdbsim_target::pid_to_str (ptid_t ptid)
{
return normal_pid_to_str (ptid);
}
/* Simulator memory may be accessed after the program has been loaded. */
static int
gdbsim_has_all_memory (struct target_ops *ops)
int
gdbsim_target::has_all_memory ()
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
@ -1286,8 +1327,8 @@ gdbsim_has_all_memory (struct target_ops *ops)
return 1;
}
static int
gdbsim_has_memory (struct target_ops *ops)
int
gdbsim_target::has_memory ()
{
struct sim_inferior_data *sim_data
= get_sim_inferior_data (current_inferior (), SIM_INSTANCE_NOT_NEEDED);
@ -1298,50 +1339,11 @@ gdbsim_has_memory (struct target_ops *ops)
return 1;
}
/* Define the target subroutine names. */
struct target_ops gdbsim_ops;
static void
init_gdbsim_ops (void)
{
gdbsim_ops.to_shortname = "sim";
gdbsim_ops.to_longname = "simulator";
gdbsim_ops.to_doc = "Use the compiled-in simulator.";
gdbsim_ops.to_open = gdbsim_open;
gdbsim_ops.to_close = gdbsim_close;
gdbsim_ops.to_detach = gdbsim_detach;
gdbsim_ops.to_resume = gdbsim_resume;
gdbsim_ops.to_wait = gdbsim_wait;
gdbsim_ops.to_fetch_registers = gdbsim_fetch_register;
gdbsim_ops.to_store_registers = gdbsim_store_register;
gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store;
gdbsim_ops.to_xfer_partial = gdbsim_xfer_partial;
gdbsim_ops.to_files_info = gdbsim_files_info;
gdbsim_ops.to_insert_breakpoint = memory_insert_breakpoint;
gdbsim_ops.to_remove_breakpoint = memory_remove_breakpoint;
gdbsim_ops.to_kill = gdbsim_kill;
gdbsim_ops.to_load = gdbsim_load;
gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
gdbsim_ops.to_interrupt = gdbsim_interrupt;
gdbsim_ops.to_thread_alive = gdbsim_thread_alive;
gdbsim_ops.to_pid_to_str = gdbsim_pid_to_str;
gdbsim_ops.to_stratum = process_stratum;
gdbsim_ops.to_has_all_memory = gdbsim_has_all_memory;
gdbsim_ops.to_has_memory = gdbsim_has_memory;
gdbsim_ops.to_has_stack = default_child_has_stack;
gdbsim_ops.to_has_registers = default_child_has_registers;
gdbsim_ops.to_has_execution = default_child_has_execution;
gdbsim_ops.to_magic = OPS_MAGIC;
}
void
_initialize_remote_sim (void)
{
struct cmd_list_element *c;
init_gdbsim_ops ();
add_target (&gdbsim_ops);
c = add_com ("sim", class_obscure, simulator_command,

File diff suppressed because it is too large Load Diff

View File

@ -74,7 +74,34 @@
# define ARCH64() (register_size (target_gdbarch (), 0) == 8)
#endif
static target_xfer_partial_ftype rs6000_xfer_shared_libraries;
class rs6000_nat_target final : public inf_ptrace_target
{
public:
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
void create_inferior (const char *, const std::string &,
char **, int) override;
ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
private:
enum target_xfer_status
xfer_shared_libraries (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len);
};
static rs6000_nat_target the_rs6000_nat_target;
/* Given REGNO, a gdb register number, return the corresponding
number suitable for use as a ptrace() parameter. Return -1 if
@ -277,9 +304,8 @@ store_register (struct regcache *regcache, int regno)
/* Read from the inferior all registers if REGNO == -1 and just register
REGNO otherwise. */
static void
rs6000_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
rs6000_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
if (regno != -1)
@ -320,9 +346,8 @@ rs6000_fetch_inferior_registers (struct target_ops *ops,
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
static void
rs6000_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regno)
void
rs6000_nat_target::store_registers (struct regcache *regcache, int regno)
{
struct gdbarch *gdbarch = regcache->arch ();
if (regno != -1)
@ -361,11 +386,12 @@ rs6000_store_inferior_registers (struct target_ops *ops,
/* Implement the to_xfer_partial target_ops method. */
static enum target_xfer_status
rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
enum target_xfer_status
rs6000_nat_target::xfer_partial (enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len)
{
pid_t pid = ptid_get_pid (inferior_ptid);
int arch64 = ARCH64 ();
@ -373,9 +399,9 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
switch (object)
{
case TARGET_OBJECT_LIBRARIES_AIX:
return rs6000_xfer_shared_libraries (ops, object, annex,
readbuf, writebuf,
offset, len, xfered_len);
return xfer_shared_libraries (object, annex,
readbuf, writebuf,
offset, len, xfered_len);
case TARGET_OBJECT_MEMORY:
{
union
@ -467,9 +493,9 @@ rs6000_xfer_partial (struct target_ops *ops, enum target_object object,
process ID of the child, or MINUS_ONE_PTID in case of error; store
the status in *OURSTATUS. */
static ptid_t
rs6000_wait (struct target_ops *ops,
ptid_t ptid, struct target_waitstatus *ourstatus, int options)
ptid_t
rs6000_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
int options)
{
pid_t pid;
int status, save_errno;
@ -524,20 +550,17 @@ rs6000_wait (struct target_ops *ops,
/* Set the current architecture from the host running GDB. Called when
starting a child process. */
static void (*super_create_inferior) (struct target_ops *,
const char *exec_file,
const std::string &allargs,
char **env, int from_tty);
static void
rs6000_create_inferior (struct target_ops * ops, const char *exec_file,
const std::string &allargs, char **env, int from_tty)
void
rs6000_nat_target::create_inferior (const char *exec_file,
const std::string &allargs,
char **env, int from_tty)
{
enum bfd_architecture arch;
unsigned long mach;
bfd abfd;
struct gdbarch_info info;
super_create_inferior (ops, exec_file, allargs, env, from_tty);
inf_ptrace_target::create_inferior (exec_file, allargs, env, from_tty);
if (__power_rs ())
{
@ -617,9 +640,9 @@ rs6000_ptrace_ldinfo (ptid_t ptid)
/* Implement the to_xfer_partial target_ops method for
TARGET_OBJECT_LIBRARIES_AIX objects. */
static enum target_xfer_status
rs6000_xfer_shared_libraries
(struct target_ops *ops, enum target_object object,
enum target_xfer_status
rs6000_nat_target::xfer_shared_libraries
(enum target_object object,
const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
{
@ -648,17 +671,5 @@ rs6000_xfer_shared_libraries
void
_initialize_rs6000_nat (void)
{
struct target_ops *t;
t = inf_ptrace_target ();
t->to_fetch_registers = rs6000_fetch_inferior_registers;
t->to_store_registers = rs6000_store_inferior_registers;
t->to_xfer_partial = rs6000_xfer_partial;
super_create_inferior = t->to_create_inferior;
t->to_create_inferior = rs6000_create_inferior;
t->to_wait = rs6000_wait;
add_target (t);
add_target (&the_rs6000_nat_target);
}

View File

@ -4885,7 +4885,7 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
return 0;
case 1014: /* Data Cache Block set to Zero */
if (target_auxv_search (&current_target, AT_DCACHEBSIZE, &at_dcsz) <= 0
if (target_auxv_search (target_stack, AT_DCACHEBSIZE, &at_dcsz) <= 0
|| at_dcsz == 0)
at_dcsz = 128; /* Assume 128-byte cache line size (POWER8) */

View File

@ -108,6 +108,36 @@ static const struct regset s390_64_gregset =
#define PER_CONTROL_SUSPENSION PER_BIT (41)
#define PER_CONTROL_ALTERATION PER_BIT (42)
class s390_linux_nat_target final : public linux_nat_target
{
public:
/* Add our register access methods. */
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
/* Add our watchpoint methods. */
int can_use_hw_breakpoint (enum bptype, int, int) override;
int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
override;
int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
int have_continuable_watchpoint () { return 1; }
int stopped_by_watchpoint () override;
int watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
/* Detect target architecture. */
const struct target_desc *read_description () override;
int auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
override;
};
static s390_linux_nat_target the_s390_linux_nat_target;
/* Fill GDB's register array with the general-purpose register values
in *REGP.
@ -369,9 +399,8 @@ check_regset (int tid, int regset, int regsize)
/* Fetch register REGNUM from the child process. If REGNUM is -1, do
this for all registers. */
static void
s390_linux_fetch_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
s390_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
{
pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -424,9 +453,8 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops,
/* Store register REGNUM back into the child process. If REGNUM is
-1, do this for all registers. */
static void
s390_linux_store_inferior_registers (struct target_ops *ops,
struct regcache *regcache, int regnum)
void
s390_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
{
pid_t tid = get_ptrace_pid (regcache_get_ptid (regcache));
@ -629,8 +657,8 @@ s390_show_debug_regs (int tid, const char *where)
per_info.lowcore.words.access_id);
}
static int
s390_stopped_by_watchpoint (struct target_ops *ops)
int
s390_linux_nat_target::stopped_by_watchpoint ()
{
struct s390_debug_reg_state *state
= s390_get_debug_reg_state (ptid_get_pid (inferior_ptid));
@ -821,10 +849,10 @@ s390_refresh_per_info (void)
return 0;
}
static int
s390_insert_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len, enum target_hw_bp_type type,
struct expression *cond)
int
s390_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
s390_watch_area area;
struct s390_debug_reg_state *state
@ -837,10 +865,10 @@ s390_insert_watchpoint (struct target_ops *self,
return s390_refresh_per_info ();
}
static int
s390_remove_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len, enum target_hw_bp_type type,
struct expression *cond)
int
s390_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
enum target_hw_bp_type type,
struct expression *cond)
{
unsigned ix;
s390_watch_area *area;
@ -865,9 +893,9 @@ s390_remove_watchpoint (struct target_ops *self,
/* Implement the "can_use_hw_breakpoint" target_ops method. */
static int
s390_can_use_hw_breakpoint (struct target_ops *self,
enum bptype type, int cnt, int othertype)
int
s390_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
int cnt, int othertype)
{
if (type == bp_hardware_watchpoint || type == bp_hardware_breakpoint)
return 1;
@ -876,10 +904,9 @@ s390_can_use_hw_breakpoint (struct target_ops *self,
/* Implement the "insert_hw_breakpoint" target_ops method. */
static int
s390_insert_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
s390_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
s390_watch_area area;
struct s390_debug_reg_state *state;
@ -894,10 +921,9 @@ s390_insert_hw_breakpoint (struct target_ops *self,
/* Implement the "remove_hw_breakpoint" target_ops method. */
static int
s390_remove_hw_breakpoint (struct target_ops *self,
struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
int
s390_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
unsigned ix;
struct watch_area *area;
@ -920,9 +946,8 @@ s390_remove_hw_breakpoint (struct target_ops *self,
return -1;
}
static int
s390_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int cnt)
int
s390_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int cnt)
{
return 1;
}
@ -946,9 +971,10 @@ s390_target_wordsize (void)
return wordsize;
}
static int
s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
int
s390_linux_nat_target::auxv_parse (gdb_byte **readptr,
gdb_byte *endptr, CORE_ADDR *typep,
CORE_ADDR *valp)
{
int sizeof_auxv_field = s390_target_wordsize ();
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
@ -969,8 +995,8 @@ s390_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
return 1;
}
static const struct target_desc *
s390_read_description (struct target_ops *ops)
const struct target_desc *
s390_linux_nat_target::read_description ()
{
int tid = s390_inferior_tid ();
@ -988,7 +1014,7 @@ s390_read_description (struct target_ops *ops)
{
CORE_ADDR hwcap = 0;
target_auxv_search (&current_target, AT_HWCAP, &hwcap);
target_auxv_search (target_stack, AT_HWCAP, &hwcap);
have_regset_tdb = (hwcap & HWCAP_S390_TE)
&& check_regset (tid, NT_S390_TDB, s390_sizeof_tdbregset);
@ -1033,31 +1059,11 @@ s390_read_description (struct target_ops *ops)
void
_initialize_s390_nat (void)
{
struct target_ops *t;
/* Fill in the generic GNU/Linux methods. */
t = linux_target ();
/* Add our register access methods. */
t->to_fetch_registers = s390_linux_fetch_inferior_registers;
t->to_store_registers = s390_linux_store_inferior_registers;
/* Add our watchpoint methods. */
t->to_can_use_hw_breakpoint = s390_can_use_hw_breakpoint;
t->to_insert_hw_breakpoint = s390_insert_hw_breakpoint;
t->to_remove_hw_breakpoint = s390_remove_hw_breakpoint;
t->to_region_ok_for_hw_watchpoint = s390_region_ok_for_hw_watchpoint;
t->to_have_continuable_watchpoint = 1;
t->to_stopped_by_watchpoint = s390_stopped_by_watchpoint;
t->to_insert_watchpoint = s390_insert_watchpoint;
t->to_remove_watchpoint = s390_remove_watchpoint;
/* Detect target architecture. */
t->to_read_description = s390_read_description;
t->to_auxv_parse = s390_auxv_parse;
struct target_ops *t = &the_s390_linux_nat_target;
/* Register the target. */
linux_nat_add_target (t);
linux_target = &the_s390_linux_nat_target;
add_target (t);
linux_nat_set_new_thread (t, s390_new_thread);
linux_nat_set_delete_thread (t, s390_delete_thread);
linux_nat_set_prepare_to_resume (t, s390_prepare_to_resume);

Some files were not shown because too many files have changed in this diff Show More