X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdbserver%2Flinux-low.h;h=05067ffc6e6fa3c7d50277b94245118ecaa57a49;hb=8677059126a84cb9f71371beb8688138a41014fc;hp=4f8801150d5908d83c568933360ffbb94e55648e;hpb=c6885a575fe3c15bd183a9f5cd1cb588ed926510;p=binutils-gdb.git diff --git a/gdbserver/linux-low.h b/gdbserver/linux-low.h index 4f8801150d5..05067ffc6e6 100644 --- a/gdbserver/linux-low.h +++ b/gdbserver/linux-low.h @@ -1,5 +1,5 @@ /* Internal interfaces for the GNU/Linux specific target code for gdbserver. - Copyright (C) 2002-2020 Free Software Foundation, Inc. + Copyright (C) 2002-2021 Free Software Foundation, Inc. This file is part of GDB. @@ -31,6 +31,8 @@ #include "target/waitstatus.h" /* For enum target_stop_reason. */ #include "tracepoint.h" +#include + #define PTRACE_XFER_TYPE long #ifdef HAVE_LINUX_REGSETS @@ -129,160 +131,584 @@ struct process_info_private struct lwp_info; -struct linux_target_ops +/* Target ops definitions for a Linux target. */ + +class linux_process_target : public process_stratum_target { - /* Architecture-specific setup. */ - void (*arch_setup) (void); +public: + + int create_inferior (const char *program, + const std::vector &program_args) override; + + void post_create_inferior () override; + + int attach (unsigned long pid) override; + + int kill (process_info *proc) override; + + int detach (process_info *proc) override; + + void mourn (process_info *proc) override; + + void join (int pid) override; + + bool thread_alive (ptid_t pid) override; + + void resume (thread_resume *resume_info, size_t n) override; + + ptid_t wait (ptid_t ptid, target_waitstatus *status, + target_wait_flags options) override; + + void fetch_registers (regcache *regcache, int regno) override; + + void store_registers (regcache *regcache, int regno) override; + + int prepare_to_access_memory () override; + + void done_accessing_memory () override; + + int read_memory (CORE_ADDR memaddr, unsigned char *myaddr, + int len) override; + + int write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, + int len) override; + + void look_up_symbols () override; + + void request_interrupt () override; + + bool supports_read_auxv () override; + + int read_auxv (CORE_ADDR offset, unsigned char *myaddr, + unsigned int len) override; + + int insert_point (enum raw_bkpt_type type, CORE_ADDR addr, + int size, raw_breakpoint *bp) override; + + int remove_point (enum raw_bkpt_type type, CORE_ADDR addr, + int size, raw_breakpoint *bp) 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; + + bool supports_hardware_single_step () override; + + bool stopped_by_watchpoint () override; + + CORE_ADDR stopped_data_address () override; + + bool supports_read_offsets () override; + + int read_offsets (CORE_ADDR *text, CORE_ADDR *data) override; + + bool supports_get_tls_address () override; + + int get_tls_address (thread_info *thread, CORE_ADDR offset, + CORE_ADDR load_module, CORE_ADDR *address) override; + + bool supports_qxfer_osdata () override; + + int qxfer_osdata (const char *annex, unsigned char *readbuf, + unsigned const char *writebuf, + CORE_ADDR offset, int len) override; + + bool supports_qxfer_siginfo () override; + + int qxfer_siginfo (const char *annex, unsigned char *readbuf, + unsigned const char *writebuf, + CORE_ADDR offset, int len) override; + + bool supports_non_stop () override; + + bool async (bool enable) override; + + int start_non_stop (bool enable) override; + + bool supports_multi_process () override; + + bool supports_fork_events () override; + + bool supports_vfork_events () override; + + bool supports_exec_events () override; + + void handle_new_gdb_connection () override; + + int handle_monitor_command (char *mon) override; - const struct regs_info *(*regs_info) (void); - int (*cannot_fetch_register) (int); + int core_of_thread (ptid_t ptid) override; - /* Returns 0 if we can store the register, 1 if we can not - store the register, and 2 if failure to store the register - is acceptable. */ - int (*cannot_store_register) (int); +#if defined PT_GETDSBT || defined PTRACE_GETFDPIC + bool supports_read_loadmap () override; + + int read_loadmap (const char *annex, CORE_ADDR offset, + unsigned char *myaddr, unsigned int len) override; +#endif + + CORE_ADDR read_pc (regcache *regcache) override; + + void write_pc (regcache *regcache, CORE_ADDR pc) override; + + bool supports_thread_stopped () override; + + bool thread_stopped (thread_info *thread) override; + + void pause_all (bool freeze) override; + + void unpause_all (bool unfreeze) override; + + void stabilize_threads () override; + + bool supports_disable_randomization () override; + + bool supports_qxfer_libraries_svr4 () override; + + int qxfer_libraries_svr4 (const char *annex, + unsigned char *readbuf, + unsigned const char *writebuf, + CORE_ADDR offset, int len) override; + + bool supports_agent () override; + +#ifdef HAVE_LINUX_BTRACE + btrace_target_info *enable_btrace (ptid_t ptid, + const btrace_config *conf) override; + + int disable_btrace (btrace_target_info *tinfo) override; + + int read_btrace (btrace_target_info *tinfo, buffer *buf, + enum btrace_read_type type) override; + + int read_btrace_conf (const btrace_target_info *tinfo, + buffer *buf) override; +#endif + + bool supports_range_stepping () override; + + bool supports_pid_to_exec_file () override; + + const char *pid_to_exec_file (int pid) override; + + bool supports_multifs () override; + + int multifs_open (int pid, const char *filename, int flags, + mode_t mode) override; + + int multifs_unlink (int pid, const char *filename) override; + + ssize_t multifs_readlink (int pid, const char *filename, char *buf, + size_t bufsiz) override; + + const char *thread_name (ptid_t thread) override; + +#if USE_THREAD_DB + bool thread_handle (ptid_t ptid, gdb_byte **handle, + int *handle_len) override; +#endif + + bool supports_catch_syscall () override; + + /* Return the information to access registers. This has public + visibility because proc-service uses it. */ + virtual const regs_info *get_regs_info () = 0; + +private: + + /* Handle a GNU/Linux extended wait response. If we see a clone, + fork, or vfork event, we need to add the new LWP to our list + (and return 0 so as not to report the trap to higher layers). + If we see an exec event, we will modify ORIG_EVENT_LWP to point + to a new LWP representing the new program. */ + int handle_extended_wait (lwp_info **orig_event_lwp, int wstat); + + /* Do low-level handling of the event, and check if this is an event we want + to report. Is so, store it as a pending status in the lwp_info structure + corresponding to LWPID. */ + void filter_event (int lwpid, int wstat); + + /* Wait for an event from child(ren) WAIT_PTID, and return any that + match FILTER_PTID (leaving others pending). The PTIDs can be: + minus_one_ptid, to specify any child; a pid PTID, specifying all + lwps of a thread group; or a PTID representing a single lwp. Store + the stop status through the status pointer WSTAT. OPTIONS is + passed to the waitpid call. Return 0 if no event was found and + OPTIONS contains WNOHANG. Return -1 if no unwaited-for children + was found. Return the PID of the stopped child otherwise. */ + int wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, + int *wstatp, int options); + + /* Wait for an event from child(ren) PTID. PTIDs can be: + minus_one_ptid, to specify any child; a pid PTID, specifying all + lwps of a thread group; or a PTID representing a single lwp. Store + the stop status through the status pointer WSTAT. OPTIONS is + passed to the waitpid call. Return 0 if no event was found and + OPTIONS contains WNOHANG. Return -1 if no unwaited-for children + was found. Return the PID of the stopped child otherwise. */ + int wait_for_event (ptid_t ptid, int *wstatp, int options); + + /* Wait for all children to stop for the SIGSTOPs we just queued. */ + void wait_for_sigstop (); + + /* Wait for process, returns status. */ + ptid_t wait_1 (ptid_t ptid, target_waitstatus *ourstatus, + target_wait_flags target_options); + + /* Stop all lwps that aren't stopped yet, except EXCEPT, if not NULL. + If SUSPEND, then also increase the suspend count of every LWP, + except EXCEPT. */ + void stop_all_lwps (int suspend, lwp_info *except); + + /* Stopped LWPs that the client wanted to be running, that don't have + pending statuses, are set to run again, except for EXCEPT, if not + NULL. This undoes a stop_all_lwps call. */ + void unstop_all_lwps (int unsuspend, lwp_info *except); + + /* Start a step-over operation on LWP. When LWP stopped at a + breakpoint, to make progress, we need to remove the breakpoint out + of the way. If we let other threads run while we do that, they may + pass by the breakpoint location and miss hitting it. To avoid + that, a step-over momentarily stops all threads while LWP is + single-stepped by either hardware or software while the breakpoint + is temporarily uninserted from the inferior. When the single-step + finishes, we reinsert the breakpoint, and let all threads that are + supposed to be running, run again. */ + void start_step_over (lwp_info *lwp); + + /* If there's a step over in progress, wait until all threads stop + (that is, until the stepping thread finishes its step), and + unsuspend all lwps. The stepping thread ends with its status + pending, which is processed later when we get back to processing + events. */ + void complete_ongoing_step_over (); + + /* Finish a step-over. Reinsert the breakpoint we had uninserted in + start_step_over, if still there, and delete any single-step + breakpoints we've set, on non hardware single-step targets. + Return true if step over finished. */ + bool finish_step_over (lwp_info *lwp); + + /* When we finish a step-over, set threads running again. If there's + another thread that may need a step-over, now's the time to start + it. Eventually, we'll move all threads past their breakpoints. */ + void proceed_all_lwps (); + + /* The reason we resume in the caller, is because we want to be able + to pass lwp->status_pending as WSTAT, and we need to clear + status_pending_p before resuming, otherwise, resume_one_lwp + refuses to resume. */ + bool maybe_move_out_of_jump_pad (lwp_info *lwp, int *wstat); + + /* Move THREAD out of the jump pad. */ + void move_out_of_jump_pad (thread_info *thread); + + /* Call low_arch_setup on THREAD. */ + void arch_setup_thread (thread_info *thread); + +#ifdef HAVE_LINUX_USRREGS + /* Fetch one register. */ + void fetch_register (const usrregs_info *usrregs, regcache *regcache, + int regno); + + /* Store one register. */ + void store_register (const usrregs_info *usrregs, regcache *regcache, + int regno); +#endif + + /* Fetch all registers, or just one, from the child process. + If REGNO is -1, do this for all registers, skipping any that are + assumed to have been retrieved by regsets_fetch_inferior_registers, + unless ALL is non-zero. + Otherwise, REGNO specifies which register (so we can save time). */ + void usr_fetch_inferior_registers (const regs_info *regs_info, + regcache *regcache, int regno, int all); + + /* Store our register values back into the inferior. + If REGNO is -1, do this for all registers, skipping any that are + assumed to have been saved by regsets_store_inferior_registers, + unless ALL is non-zero. + Otherwise, REGNO specifies which register (so we can save time). */ + void usr_store_inferior_registers (const regs_info *regs_info, + regcache *regcache, int regno, int all); + + /* Return the PC as read from the regcache of LWP, without any + adjustment. */ + CORE_ADDR get_pc (lwp_info *lwp); + + /* Called when the LWP stopped for a signal/trap. If it stopped for a + trap check what caused it (breakpoint, watchpoint, trace, etc.), + and save the result in the LWP's stop_reason field. If it stopped + for a breakpoint, decrement the PC if necessary on the lwp's + architecture. Returns true if we now have the LWP's stop PC. */ + bool save_stop_reason (lwp_info *lwp); + + /* Resume execution of LWP. If STEP is nonzero, single-step it. If + SIGNAL is nonzero, give it that signal. */ + void resume_one_lwp_throw (lwp_info *lwp, int step, int signal, + siginfo_t *info); + + /* Like resume_one_lwp_throw, but no error is thrown if the LWP + disappears while we try to resume it. */ + void resume_one_lwp (lwp_info *lwp, int step, int signal, siginfo_t *info); + + /* This function is called once per thread. We check the thread's + last resume request, which will tell us whether to resume, step, or + leave the thread stopped. Any signal the client requested to be + delivered has already been enqueued at this point. + + If any thread that GDB wants running is stopped at an internal + breakpoint that needs stepping over, we start a step-over operation + on that particular thread, and leave all others stopped. */ + void proceed_one_lwp (thread_info *thread, lwp_info *except); + + /* This function is called once per thread. We check the thread's + resume request, which will tell us whether to resume, step, or + leave the thread stopped; and what signal, if any, it should be + sent. + + For threads which we aren't explicitly told otherwise, we preserve + the stepping flag; this is used for stepping over gdbserver-placed + breakpoints. + + If pending_flags was set in any thread, we queue any needed + signals, since we won't actually resume. We already have a pending + event to report, so we don't need to preserve any step requests; + they should be re-issued if necessary. */ + void resume_one_thread (thread_info *thread, bool leave_all_stopped); + + /* Return true if this lwp has an interesting status pending. */ + bool status_pending_p_callback (thread_info *thread, ptid_t ptid); + + /* Resume LWPs that are currently stopped without any pending status + to report, but are resumed from the core's perspective. */ + void resume_stopped_resumed_lwps (thread_info *thread); + + /* Unsuspend THREAD, except EXCEPT, and proceed. */ + void unsuspend_and_proceed_one_lwp (thread_info *thread, lwp_info *except); + + /* Return true if this lwp still has an interesting status pending. + If not (e.g., it had stopped for a breakpoint that is gone), return + false. */ + bool thread_still_has_status_pending (thread_info *thread); + + /* Return true if this lwp is to-be-resumed and has an interesting + status pending. */ + bool resume_status_pending (thread_info *thread); + + /* Return true if this lwp that GDB wants running is stopped at an + internal breakpoint that we need to step over. It assumes that + any required STOP_PC adjustment has already been propagated to + the inferior's regcache. */ + bool thread_needs_step_over (thread_info *thread); + + /* Single step via hardware or software single step. + Return 1 if hardware single stepping, 0 if software single stepping + or can't single step. */ + int single_step (lwp_info* lwp); + + /* Return true if THREAD is doing hardware single step. */ + bool maybe_hw_step (thread_info *thread); + + /* Install breakpoints for software single stepping. */ + void install_software_single_step_breakpoints (lwp_info *lwp); + + /* Fetch the possibly triggered data watchpoint info and store it in + CHILD. + + On some archs, like x86, that use debug registers to set + watchpoints, it's possible that the way to know which watched + address trapped, is to check the register that is used to select + which address to watch. Problem is, between setting the watchpoint + and reading back which data address trapped, the user may change + the set of watchpoints, and, as a consequence, GDB changes the + debug registers in the inferior. To avoid reading back a stale + stopped-data-address when that happens, we cache in LP the fact + that a watchpoint trapped, and the corresponding data address, as + soon as we see CHILD stop with a SIGTRAP. If GDB changes the debug + registers meanwhile, we have the cached data we can rely on. */ + bool check_stopped_by_watchpoint (lwp_info *child); + + /* Convert a native/host siginfo object, into/from the siginfo in the + layout of the inferiors' architecture. */ + void siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, + int direction); + + /* Add a process to the common process list, and set its private + data. */ + process_info *add_linux_process (int pid, int attached); + + /* Add a new thread. */ + lwp_info *add_lwp (ptid_t ptid); + + /* Delete a thread. */ + void delete_lwp (lwp_info *lwp); + +public: /* Make this public because it's used from outside. */ + /* Attach to an inferior process. Returns 0 on success, ERRNO on + error. */ + int attach_lwp (ptid_t ptid); + +private: /* Back to private. */ + /* Detach from LWP. */ + void detach_one_lwp (lwp_info *lwp); + + /* Detect zombie thread group leaders, and "exit" them. We can't + reap their exits until all other threads in the group have + exited. */ + void check_zombie_leaders (); + + /* Convenience function that is called when the kernel reports an exit + event. This decides whether to report the event to GDB as a + process exit event, a thread exit event, or to suppress the + event. */ + ptid_t filter_exit_event (lwp_info *event_child, + target_waitstatus *ourstatus); + + /* Returns true if THREAD is stopped in a jump pad, and we can't + move it out, because we need to report the stop event to GDB. For + example, if the user puts a breakpoint in the jump pad, it's + because she wants to debug it. */ + bool stuck_in_jump_pad (thread_info *thread); + + /* Convenience wrapper. Returns information about LWP's fast tracepoint + collection status. */ + fast_tpoint_collect_result linux_fast_tracepoint_collecting + (lwp_info *lwp, fast_tpoint_collect_status *status); + + /* This function should only be called if LWP got a SYSCALL_SIGTRAP. + Fill *SYSNO with the syscall nr trapped. */ + void get_syscall_trapinfo (lwp_info *lwp, int *sysno); + + /* Returns true if GDB is interested in the event_child syscall. + Only to be called when stopped reason is SYSCALL_SIGTRAP. */ + bool gdb_catch_this_syscall (lwp_info *event_child); + +protected: + /* The architecture-specific "low" methods are listed below. */ + + /* Architecture-specific setup for the current thread. */ + virtual void low_arch_setup () = 0; + + /* Return false if we can fetch/store the register, true if we cannot + fetch/store the register. */ + virtual bool low_cannot_fetch_register (int regno) = 0; + + virtual bool low_cannot_store_register (int regno) = 0; /* Hook to fetch a register in some non-standard way. Used for example by backends that have read-only registers with hardcoded values (e.g., IA64's gr0/fr0/fr1). Returns true if register REGNO was supplied, false if not, and we should fallback to the standard ptrace methods. */ - int (*fetch_register) (struct regcache *regcache, int regno); + virtual bool low_fetch_register (regcache *regcache, int regno); - CORE_ADDR (*get_pc) (struct regcache *regcache); - void (*set_pc) (struct regcache *regcache, CORE_ADDR newpc); + /* Return true if breakpoints are supported. Such targets must + implement the GET_PC and SET_PC methods. */ + virtual bool low_supports_breakpoints (); - /* See target.h for details. */ - int (*breakpoint_kind_from_pc) (CORE_ADDR *pcptr); + virtual CORE_ADDR low_get_pc (regcache *regcache); - /* See target.h for details. */ - const gdb_byte *(*sw_breakpoint_from_kind) (int kind, int *size); + virtual void low_set_pc (regcache *regcache, CORE_ADDR newpc); - /* Find the next possible PCs after the current instruction executes. */ - std::vector (*get_next_pcs) (struct regcache *regcache); + /* Find the next possible PCs after the current instruction executes. + Targets that override this method should also override + 'supports_software_single_step' to return true. */ + virtual std::vector low_get_next_pcs (regcache *regcache); - int decr_pc_after_break; - int (*breakpoint_at) (CORE_ADDR pc); + /* Return true if there is a breakpoint at PC. */ + virtual bool low_breakpoint_at (CORE_ADDR pc) = 0; /* Breakpoint and watchpoint related functions. See target.h for comments. */ - int (*supports_z_point_type) (char z_type); - int (*insert_point) (enum raw_bkpt_type type, CORE_ADDR addr, - int size, struct raw_breakpoint *bp); - int (*remove_point) (enum raw_bkpt_type type, CORE_ADDR addr, - int size, struct raw_breakpoint *bp); + virtual int low_insert_point (raw_bkpt_type type, CORE_ADDR addr, + int size, raw_breakpoint *bp); + + virtual int low_remove_point (raw_bkpt_type type, CORE_ADDR addr, + int size, raw_breakpoint *bp); - int (*stopped_by_watchpoint) (void); - CORE_ADDR (*stopped_data_address) (void); + virtual bool low_stopped_by_watchpoint (); + + virtual CORE_ADDR low_stopped_data_address (); /* Hooks to reformat register data for PEEKUSR/POKEUSR (in particular for registers smaller than an xfer unit). */ - void (*collect_ptrace_register) (struct regcache *regcache, - int regno, char *buf); - void (*supply_ptrace_register) (struct regcache *regcache, - int regno, const char *buf); + virtual void low_collect_ptrace_register (regcache *regcache, int regno, + char *buf); + + virtual void low_supply_ptrace_register (regcache *regcache, int regno, + const char *buf); /* Hook to convert from target format to ptrace format and back. Returns true if any conversion was done; false otherwise. If DIRECTION is 1, then copy from INF to NATIVE. If DIRECTION is 0, copy from NATIVE to INF. */ - int (*siginfo_fixup) (siginfo_t *native, gdb_byte *inf, int direction); + virtual bool low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, + int direction); /* Hook to call when a new process is created or attached to. If extra per-process architecture-specific data is needed, allocate it here. */ - struct arch_process_info * (*new_process) (void); + virtual arch_process_info *low_new_process (); /* Hook to call when a process is being deleted. If extra per-process architecture-specific data is needed, delete it here. */ - void (*delete_process) (struct arch_process_info *info); + virtual void low_delete_process (arch_process_info *info); /* Hook to call when a new thread is detected. If extra per-thread architecture-specific data is needed, allocate it here. */ - void (*new_thread) (struct lwp_info *); + virtual void low_new_thread (lwp_info *); /* Hook to call when a thread is being deleted. If extra per-thread architecture-specific data is needed, delete it here. */ - void (*delete_thread) (struct arch_lwp_info *); + virtual void low_delete_thread (arch_lwp_info *); /* Hook to call, if any, when a new fork is attached. */ - void (*new_fork) (struct process_info *parent, struct process_info *child); + virtual void low_new_fork (process_info *parent, process_info *child); /* Hook to call prior to resuming a thread. */ - void (*prepare_to_resume) (struct lwp_info *); - - /* Hook to support target specific qSupported. */ - void (*process_qsupported) (char **, int count); - - /* Returns true if the low target supports tracepoints. */ - int (*supports_tracepoints) (void); + virtual void low_prepare_to_resume (lwp_info *lwp); /* Fill ADDRP with the thread area address of LWPID. Returns 0 on success, -1 on failure. */ - int (*get_thread_area) (int lwpid, CORE_ADDR *addrp); - - /* Install a fast tracepoint jump pad. See target.h for - comments. */ - int (*install_fast_tracepoint_jump_pad) (CORE_ADDR tpoint, CORE_ADDR tpaddr, - CORE_ADDR collector, - CORE_ADDR lockaddr, - ULONGEST orig_size, - CORE_ADDR *jump_entry, - CORE_ADDR *trampoline, - ULONGEST *trampoline_size, - unsigned char *jjump_pad_insn, - ULONGEST *jjump_pad_insn_size, - CORE_ADDR *adjusted_insn_addr, - CORE_ADDR *adjusted_insn_addr_end, - char *err); - - /* Return the bytecode operations vector for the current inferior. - Returns NULL if bytecode compilation is not supported. */ - struct emit_ops *(*emit_ops) (void); - - /* Return the minimum length of an instruction that can be safely overwritten - for use as a fast tracepoint. */ - int (*get_min_fast_tracepoint_insn_len) (void); + virtual int low_get_thread_area (int lwpid, CORE_ADDR *addrp); /* Returns true if the low target supports range stepping. */ - int (*supports_range_stepping) (void); - - /* See target.h. */ - int (*breakpoint_kind_from_current_state) (CORE_ADDR *pcptr); + virtual bool low_supports_range_stepping (); - /* See target.h. */ - int (*supports_hardware_single_step) (void); + /* Return true if the target supports catch syscall. Such targets + override the low_get_syscall_trapinfo method below. */ + virtual bool low_supports_catch_syscall (); /* Fill *SYSNO with the syscall nr trapped. Only to be called when inferior is stopped due to SYSCALL_SIGTRAP. */ - void (*get_syscall_trapinfo) (struct regcache *regcache, int *sysno); + virtual void low_get_syscall_trapinfo (regcache *regcache, int *sysno); - /* See target.h. */ - int (*get_ipa_tdesc_idx) (void); + /* How many bytes the PC should be decremented after a break. */ + virtual int low_decr_pc_after_break (); }; -extern struct linux_target_ops the_low_target; +extern linux_process_target *the_linux_target; -/* Target ops definitions for a Linux target. */ - -class linux_process_target : public process_target -{ -public: - - int create_inferior (const char *program, - const std::vector &program_args) override; +#define get_thread_lwp(thr) ((struct lwp_info *) (thread_target_data (thr))) +#define get_lwp_thread(lwp) ((lwp)->thread) - void post_create_inferior () override; +/* Information about a signal that is to be delivered to a thread. */ - int attach (unsigned long pid) override; +struct pending_signal +{ + pending_signal (int signal) + : signal {signal} + {}; - int kill (process_info *proc) override; + int signal; + siginfo_t info; }; -#define get_thread_lwp(thr) ((struct lwp_info *) (thread_target_data (thr))) -#define get_lwp_thread(lwp) ((lwp)->thread) - /* This struct is recorded in the target_data field of struct thread_info. On linux ``all_threads'' is keyed by the LWP ID, which we use as the @@ -296,7 +722,7 @@ public: struct lwp_info { /* Backlink to the parent object. */ - struct thread_info *thread; + struct thread_info *thread = nullptr; /* If this flag is set, the next SIGSTOP will be ignored (the process will be immediately resumed). This means that either we @@ -304,25 +730,25 @@ struct lwp_info (so the SIGSTOP is still pending), or that we stopped the inferior implicitly via PTRACE_ATTACH and have not waited for it yet. */ - int stop_expected; + int stop_expected = 0; /* When this is true, we shall not try to resume this thread, even if last_resume_kind isn't resume_stop. */ - int suspended; + int suspended = 0; /* If this flag is set, the lwp is known to be stopped right now (stop event already received in a wait()). */ - int stopped; + int stopped = 0; /* 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; + enum target_waitkind syscall_state = TARGET_WAITKIND_SYSCALL_ENTRY; /* When stopped is set, the last wait status recorded for this lwp. */ - int last_status; + int last_status = 0; /* If WAITSTATUS->KIND != TARGET_WAITKIND_IGNORE, the waitstatus for this LWP's last event, to pass to GDB without any further @@ -334,81 +760,81 @@ struct lwp_info the parent fork event is not reported to higher layers. Used to avoid wildcard vCont actions resuming a fork child before GDB is notified about the parent's fork event. */ - struct lwp_info *fork_relative; + struct lwp_info *fork_relative = nullptr; /* When stopped is set, this is where the lwp last stopped, with decr_pc_after_break already accounted for. If the LWP is running, this is the address at which the lwp was resumed. */ - CORE_ADDR stop_pc; + CORE_ADDR stop_pc = 0; /* If this flag is set, STATUS_PENDING is a waitstatus that has not yet been reported. */ - int status_pending_p; - int status_pending; + int status_pending_p = 0; + int status_pending = 0; /* The reason the LWP last stopped, if we need to track it (breakpoint, watchpoint, etc.) */ - enum target_stop_reason stop_reason; + enum 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 is non-zero, and contains such data address. Only valid if STOPPED_BY_WATCHPOINT is true. */ - CORE_ADDR stopped_data_address; + CORE_ADDR stopped_data_address = 0; /* If this is non-zero, it is a breakpoint to be reinserted at our next stop (SIGTRAP stops only). */ - CORE_ADDR bp_reinsert; + CORE_ADDR bp_reinsert = 0; /* If this flag is set, the last continue operation at the ptrace level on this process was a single-step. */ - int stepping; + int stepping = 0; /* Range to single step within. This is a copy of the step range passed along the last resume request. See 'struct thread_resume'. */ - CORE_ADDR step_range_start; /* Inclusive */ - CORE_ADDR step_range_end; /* Exclusive */ + CORE_ADDR step_range_start = 0; /* Inclusive */ + CORE_ADDR step_range_end = 0; /* Exclusive */ /* 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; + int must_set_ptrace_flags = 0; - /* If this is non-zero, it points to a chain of signals which need to - be delivered to this process. */ - struct pending_signals *pending_signals; + /* A chain of signals that need to be delivered to this process. */ + std::list pending_signals; /* A link used when resuming. It is initialized from the resume request, and then processed and cleared in linux_resume_one_lwp. */ - struct thread_resume *resume; + struct thread_resume *resume = nullptr; /* Information bout this lwp's fast tracepoint collection status (is it currently stopped in the jump pad, and if so, before or at/after the relocated instruction). Normally, we won't care about this, but we will if a signal arrives to this lwp while it is collecting. */ - fast_tpoint_collect_result collecting_fast_tracepoint; + fast_tpoint_collect_result collecting_fast_tracepoint + = fast_tpoint_collect_result::not_collecting; - /* If this is non-zero, it points to a chain of signals which need - to be reported to GDB. These were deferred because the thread - was doing a fast tracepoint collect when they arrived. */ - struct pending_signals *pending_signals_to_report; + /* A chain of signals that need to be reported to GDB. These were + deferred because the thread was doing a fast tracepoint collect + when they arrived. */ + std::list pending_signals_to_report; /* When collecting_fast_tracepoint is first found to be 1, we insert a exit-jump-pad-quickly breakpoint. This is it. */ - struct breakpoint *exit_jump_pad_bkpt; + struct breakpoint *exit_jump_pad_bkpt = nullptr; #ifdef USE_THREAD_DB - int thread_known; + int thread_known = 0; /* The thread handle, used for e.g. TLS access. Only valid if THREAD_KNOWN is set. */ - td_thrhandle_t th; + td_thrhandle_t th {}; /* The pthread_t handle. */ - thread_t thread_handle; + thread_t thread_handle {}; #endif /* Arch-specific additions. */ - struct arch_lwp_info *arch_private; + struct arch_lwp_info *arch_private = nullptr; }; int linux_pid_exe_is_elf_64_file (int pid, unsigned int *machine);