123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- /* Native debugging support for GNU/Linux (LWP layer).
- Copyright (C) 2000-2022 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 LINUX_NAT_H
- #define LINUX_NAT_H
- #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 *, target_wait_flags) override;
- void pass_signals (gdb::array_view<const 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;
- bool thread_alive (ptid_t ptid) override;
- void update_thread_list () override;
- std::string pid_to_str (ptid_t) override;
- const char *thread_name (struct thread_info *) override;
- struct address_space *thread_address_space (ptid_t) override;
- bool stopped_by_watchpoint () override;
- bool stopped_data_address (CORE_ADDR *) override;
- bool stopped_by_sw_breakpoint () override;
- bool supports_stopped_by_sw_breakpoint () override;
- bool stopped_by_hw_breakpoint () override;
- bool supports_stopped_by_hw_breakpoint () override;
- void thread_events (int) override;
- bool can_async_p () override;
- bool supports_non_stop () override;
- bool always_non_stop_p () override;
- void async (int) override;
- void stop (ptid_t) override;
- bool supports_multi_process () override;
- bool supports_disable_randomization () override;
- int core_of_thread (ptid_t ptid) override;
- bool 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_attach (int) override;
- void follow_fork (inferior *, ptid_t, target_waitkind, bool, bool) 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 bool low_stopped_by_watchpoint ()
- { return false; }
- virtual bool low_stopped_data_address (CORE_ADDR *addr_p)
- { return false; }
- /* The method to call, if any, when a new thread is attached. */
- virtual void low_new_thread (struct lwp_info *)
- {}
- /* The method to call, if any, when a thread is destroyed. */
- virtual void low_delete_thread (struct arch_lwp_info *lp)
- {
- gdb_assert (lp == NULL);
- }
- /* The method to call, if any, when a new fork is attached. */
- virtual void low_new_fork (struct lwp_info *parent, pid_t child_pid)
- {}
- /* The method to call, if any, when a new clone event is detected. */
- virtual void low_new_clone (struct lwp_info *parent, pid_t child_lwp)
- {}
- /* The method to call, if any, when a process is no longer
- attached. */
- virtual void low_forget_process (pid_t pid)
- {}
- /* Hook to call prior to resuming a thread. */
- virtual void low_prepare_to_resume (struct lwp_info *)
- {}
- /* Convert a ptrace/host siginfo object, into/from the siginfo in
- the layout of the inferiors' architecture. Returns true if any
- conversion was done; false otherwise, in which case the caller
- does a straight memcpy. If DIRECTION is 1, then copy from INF to
- PTRACE. If DIRECTION is 0, copy from PTRACE to INF. */
- virtual bool low_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf,
- int direction)
- { return false; }
- /* SIGTRAP-like breakpoint status events recognizer. The default
- recognizes SIGTRAP only. */
- virtual bool low_status_is_event (int status);
- protected:
- void post_startup_inferior (ptid_t) override;
- };
- /* The final/concrete instance. */
- extern linux_nat_target *linux_target;
- struct arch_lwp_info;
- /* Structure describing an LWP. */
- struct lwp_info : intrusive_list_node<lwp_info>
- {
- lwp_info (ptid_t ptid)
- : ptid (ptid)
- {}
- ~lwp_info ();
- DISABLE_COPY_AND_ASSIGN (lwp_info);
- /* The process id of the LWP. This is a combination of the LWP id
- and overall process id. */
- ptid_t ptid = null_ptid;
- /* If this flag is set, we need to set the event request flags the
- next time we see this LWP stop. */
- int must_set_ptrace_flags = 0;
- /* Non-zero if we sent this LWP a SIGSTOP (but the LWP didn't report
- it back yet). */
- int signalled = 0;
- /* Non-zero if this LWP is stopped. */
- int stopped = 0;
- /* Non-zero if this LWP will be/has been resumed. Note that an LWP
- can be marked both as stopped and resumed at the same time. This
- happens if we try to resume an LWP that has a wait status
- pending. We shouldn't let the LWP run until that wait status has
- been processed, but we should not report that wait status if GDB
- didn't try to let the LWP run. */
- int resumed = 0;
- /* The last resume GDB requested on this thread. */
- resume_kind last_resume_kind = resume_continue;
- /* If non-zero, a pending wait status. */
- int status = 0;
- /* When 'stopped' is set, this is where the lwp last stopped, with
- decr_pc_after_break already accounted for. If the LWP is
- running and stepping, this is the address at which the lwp was
- resumed (that is, it's the previous stop PC). If the LWP is
- running and not stepping, this is 0. */
- CORE_ADDR stop_pc = 0;
- /* Non-zero if we were stepping this LWP. */
- int step = 0;
- /* The reason the LWP last stopped, if we need to track it
- (breakpoint, watchpoint, etc.). */
- target_stop_reason stop_reason = TARGET_STOPPED_BY_NO_REASON;
- /* On architectures where it is possible to know the data address of
- a triggered watchpoint, STOPPED_DATA_ADDRESS_P is non-zero, and
- STOPPED_DATA_ADDRESS contains such data address. Otherwise,
- STOPPED_DATA_ADDRESS_P is false, and STOPPED_DATA_ADDRESS is
- undefined. Only valid if STOPPED_BY_WATCHPOINT is true. */
- int stopped_data_address_p = 0;
- CORE_ADDR stopped_data_address = 0;
- /* Non-zero if we expect a duplicated SIGINT. */
- int ignore_sigint = 0;
- /* If WAITSTATUS->KIND != TARGET_WAITKIND_SPURIOUS, the waitstatus
- for this LWP's last event. This may correspond to STATUS above,
- or to a local variable in lin_lwp_wait. */
- struct target_waitstatus waitstatus;
- /* Signal whether we are in a SYSCALL_ENTRY or
- in a SYSCALL_RETURN event.
- Values:
- - TARGET_WAITKIND_SYSCALL_ENTRY
- - TARGET_WAITKIND_SYSCALL_RETURN */
- enum target_waitkind syscall_state;
- /* The processor core this LWP was last seen on. */
- int core = -1;
- /* Arch-specific additions. */
- struct arch_lwp_info *arch_private = nullptr;
- };
- /* lwp_info iterator and range types. */
- using lwp_info_iterator
- = reference_to_pointer_iterator<intrusive_list<lwp_info>::iterator>;
- using lwp_info_range = iterator_range<lwp_info_iterator>;
- using lwp_info_safe_range = basic_safe_range<lwp_info_range>;
- /* Get an iterable range over all lwps. */
- lwp_info_range all_lwps ();
- /* Same as the above, but safe against deletion while iterating. */
- lwp_info_safe_range all_lwps_safe ();
- /* Does the current host support PTRACE_GETREGSET? */
- extern enum tribool have_ptrace_getregset;
- /* Called from the LWP layer to inform the thread_db layer that PARENT
- spawned CHILD. Both LWPs are currently stopped. This function
- does whatever is required to have the child LWP under the
- thread_db's control --- e.g., enabling event reporting. Returns
- true on success, false if the process isn't using libpthread. */
- extern int thread_db_notice_clone (ptid_t parent, ptid_t child);
- /* Return the number of signals used by the threads library. */
- extern unsigned int lin_thread_get_thread_signal_num (void);
- /* Return the i-th signal used by the threads library. */
- extern int lin_thread_get_thread_signal (unsigned int i);
- /* Find process PID's pending signal set from /proc/pid/status. */
- void linux_proc_pending_signals (int pid, sigset_t *pending,
- sigset_t *blocked, sigset_t *ignored);
- /* For linux_stop_lwp see nat/linux-nat.h. */
- /* Stop all LWPs, synchronously. (Any events that trigger while LWPs
- are being stopped are left pending.) */
- extern void linux_stop_and_wait_all_lwps (void);
- /* Set resumed LWPs running again, as they were before being stopped
- with linux_stop_and_wait_all_lwps. (LWPS with pending events are
- left stopped.) */
- extern void linux_unstop_all_lwps (void);
- /* Update linux-nat internal state when changing from one fork
- to another. */
- void linux_nat_switch_fork (ptid_t new_ptid);
- /* Store the saved siginfo associated with PTID in *SIGINFO.
- Return 1 if it was retrieved successfully, 0 otherwise (*SIGINFO is
- uninitialized in such case). */
- int linux_nat_get_siginfo (ptid_t ptid, siginfo_t *siginfo);
- #endif /* LINUX_NAT_H */
|