X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdbserver%2Flinux-low.cc;h=9684922d1a1026a09cde6d43a55007a3947928ea;hb=013e3554b269aa1da0fcd478969f0df65341e50e;hp=47b2ef9fd316da372b84907b22df9cd2ebf4f3a3;hpb=bf9ae9d8c37a4e1dfd192f266c20ea5786fd1bbd;p=deliverable%2Fbinutils-gdb.git diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index 47b2ef9fd3..9684922d1a 100644 --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc @@ -86,11 +86,6 @@ #define PT_TEXT_ADDR 49*4 #define PT_DATA_ADDR 50*4 #define PT_TEXT_END_ADDR 51*4 -/* BFIN already defines these since at least 2.6.32 kernels. */ -#elif defined(BFIN) -#define PT_TEXT_ADDR 220 -#define PT_TEXT_END_ADDR 224 -#define PT_DATA_ADDR 228 /* These are still undefined in 3.10 kernels. */ #elif defined(__TMS320C6X__) #define PT_TEXT_ADDR (0x10000*4) @@ -268,10 +263,8 @@ int using_threads = 1; static int stabilizing_threads; static void unsuspend_all_lwps (struct lwp_info *except); -static struct lwp_info *add_lwp (ptid_t ptid); static void mark_lwp_dead (struct lwp_info *lwp, int wstat); static int lwp_is_marked_dead (struct lwp_info *lwp); -static int finish_step_over (struct lwp_info *lwp); static int kill_lwp (unsigned long lwpid, int signo); static void enqueue_pending_signal (struct lwp_info *lwp, int signal, siginfo_t *info); static int linux_low_ptrace_options (int attached); @@ -281,26 +274,6 @@ static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp); being stepped. */ ptid_t step_over_bkpt; -/* True if the low target can hardware single-step. */ - -static int -can_hardware_single_step (void) -{ - if (the_low_target.supports_hardware_single_step != NULL) - return the_low_target.supports_hardware_single_step (); - else - return 0; -} - -/* True if the low target can software single-step. Such targets - implement the GET_NEXT_PCS callback. */ - -static int -can_software_single_step (void) -{ - return (the_low_target.get_next_pcs != NULL); -} - bool linux_process_target::low_supports_breakpoints () { @@ -319,14 +292,17 @@ linux_process_target::low_set_pc (regcache *regcache, CORE_ADDR newpc) gdb_assert_not_reached ("linux target op low_set_pc is not implemented"); } -/* Returns true if this target can support fast tracepoints. This - does not mean that the in-process agent has been loaded in the - inferior. */ +std::vector +linux_process_target::low_get_next_pcs (regcache *regcache) +{ + gdb_assert_not_reached ("linux target op low_get_next_pcs is not " + "implemented"); +} -static int -supports_fast_tracepoints (void) +int +linux_process_target::low_decr_pc_after_break () { - return the_low_target.install_fast_tracepoint_jump_pad != NULL; + return 0; } /* True if LWP is stopped in its stepping range. */ @@ -339,13 +315,6 @@ lwp_in_step_range (struct lwp_info *lwp) return (pc >= lwp->step_range_start && pc < lwp->step_range_end); } -struct pending_signals -{ - int signal; - siginfo_t info; - struct pending_signals *prev; -}; - /* The read/write ends of the pipe registered as waitable file in the event loop. */ static int linux_event_pipe[2] = { -1, -1 }; @@ -409,8 +378,8 @@ linux_pid_exe_is_elf_64_file (int pid, unsigned int *machine) return elf_64_file_p (file, machine); } -static void -delete_lwp (struct lwp_info *lwp) +void +linux_process_target::delete_lwp (lwp_info *lwp) { struct thread_info *thr = get_lwp_thread (lwp); @@ -419,31 +388,52 @@ delete_lwp (struct lwp_info *lwp) remove_thread (thr); - if (the_low_target.delete_thread != NULL) - the_low_target.delete_thread (lwp->arch_private); - else - gdb_assert (lwp->arch_private == NULL); + low_delete_thread (lwp->arch_private); - free (lwp); + delete lwp; } -/* Add a process to the common process list, and set its private - data. */ +void +linux_process_target::low_delete_thread (arch_lwp_info *info) +{ + /* Default implementation should be overridden if architecture-specific + info is being used. */ + gdb_assert (info == nullptr); +} -static struct process_info * -linux_add_process (int pid, int attached) +process_info * +linux_process_target::add_linux_process (int pid, int attached) { struct process_info *proc; proc = add_process (pid, attached); proc->priv = XCNEW (struct process_info_private); - if (the_low_target.new_process != NULL) - proc->priv->arch_private = the_low_target.new_process (); + proc->priv->arch_private = low_new_process (); return proc; } +arch_process_info * +linux_process_target::low_new_process () +{ + return nullptr; +} + +void +linux_process_target::low_delete_process (arch_process_info *info) +{ + /* Default implementation must be overridden if architecture-specific + info exists. */ + gdb_assert (info == nullptr); +} + +void +linux_process_target::low_new_fork (process_info *parent, process_info *child) +{ + /* Nop. */ +} + void linux_process_target::arch_setup_thread (thread_info *thread) { @@ -524,7 +514,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, will be detached, since we will need the process object and the breakpoints to remove any breakpoints from memory when we detach, and the client side will access registers. */ - child_proc = linux_add_process (new_pid, 0); + child_proc = add_linux_process (new_pid, 0); gdb_assert (child_proc != NULL); child_lwp = add_lwp (ptid); gdb_assert (child_lwp != NULL); @@ -551,7 +541,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, child_proc->attached = parent_proc->attached; if (event_lwp->bp_reinsert != 0 - && can_software_single_step () + && supports_software_single_step () && event == PTRACE_EVENT_VFORK) { /* If we leave single-step breakpoints there, child will @@ -568,8 +558,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, child_proc->tdesc = tdesc; /* Clone arch-specific process data. */ - if (the_low_target.new_fork != NULL) - the_low_target.new_fork (parent_proc, child_proc); + low_new_fork (parent_proc, child_proc); /* Save fork info in the parent thread. */ if (event == PTRACE_EVENT_FORK) @@ -596,7 +585,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, In case of vfork, we'll reinsert them back once vforked child is done. */ if (event_lwp->bp_reinsert != 0 - && can_software_single_step ()) + && supports_software_single_step ()) { /* The child process is forked and stopped, so it is safe to access its memory without stopping all other threads @@ -660,7 +649,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, { event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORK_DONE; - if (event_lwp->bp_reinsert != 0 && can_software_single_step ()) + if (event_lwp->bp_reinsert != 0 && supports_software_single_step ()) { reinsert_single_step_breakpoints (event_thr); @@ -696,7 +685,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, current_thread = NULL; /* Create a new process/lwp/thread. */ - proc = linux_add_process (event_pid, 0); + proc = add_linux_process (event_pid, 0); event_lwp = add_lwp (event_ptid); event_thr = get_lwp_thread (event_lwp); gdb_assert (current_thread == event_thr); @@ -753,28 +742,17 @@ linux_process_target::get_pc (lwp_info *lwp) return pc; } -/* This function should only be called if LWP got a SYSCALL_SIGTRAP. - Fill *SYSNO with the syscall nr trapped. */ - -static void -get_syscall_trapinfo (struct lwp_info *lwp, int *sysno) +void +linux_process_target::get_syscall_trapinfo (lwp_info *lwp, int *sysno) { struct thread_info *saved_thread; struct regcache *regcache; - if (the_low_target.get_syscall_trapinfo == NULL) - { - /* If we cannot get the syscall trapinfo, report an unknown - system call number. */ - *sysno = UNKNOWN_SYSCALL; - return; - } - saved_thread = current_thread; current_thread = get_lwp_thread (lwp); regcache = get_thread_regcache (current_thread, 1); - (*the_low_target.get_syscall_trapinfo) (regcache, sysno); + low_get_syscall_trapinfo (regcache, sysno); if (debug_threads) debug_printf ("get_syscall_trapinfo sysno %d\n", *sysno); @@ -782,7 +760,12 @@ get_syscall_trapinfo (struct lwp_info *lwp, int *sysno) current_thread = saved_thread; } -static int check_stopped_by_watchpoint (struct lwp_info *child); +void +linux_process_target::low_get_syscall_trapinfo (regcache *regcache, int *sysno) +{ + /* By default, report an unknown system call number. */ + *sysno = UNKNOWN_SYSCALL; +} bool linux_process_target::save_stop_reason (lwp_info *lwp) @@ -798,7 +781,7 @@ linux_process_target::save_stop_reason (lwp_info *lwp) return false; pc = get_pc (lwp); - sw_breakpoint_pc = pc - the_low_target.decr_pc_after_break; + sw_breakpoint_pc = pc - low_decr_pc_after_break (); /* breakpoint_at reads from the current thread. */ saved_thread = current_thread; @@ -852,7 +835,7 @@ linux_process_target::save_stop_reason (lwp_info *lwp) then the user inserts a breakpoint inside the range. In that case we need to report the breakpoint PC. */ if ((!lwp->stepping || lwp->stop_pc == sw_breakpoint_pc) - && (*the_low_target.breakpoint_at) (sw_breakpoint_pc)) + && low_breakpoint_at (sw_breakpoint_pc)) lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; if (hardware_breakpoint_inserted_here (pc)) @@ -919,23 +902,28 @@ linux_process_target::save_stop_reason (lwp_info *lwp) return true; } -static struct lwp_info * -add_lwp (ptid_t ptid) +lwp_info * +linux_process_target::add_lwp (ptid_t ptid) { struct lwp_info *lwp; - lwp = XCNEW (struct lwp_info); + lwp = new lwp_info {}; lwp->waitstatus.kind = TARGET_WAITKIND_IGNORE; lwp->thread = add_thread (ptid, lwp); - if (the_low_target.new_thread != NULL) - the_low_target.new_thread (lwp); + low_new_thread (lwp); return lwp; } +void +linux_process_target::low_new_thread (lwp_info *info) +{ + /* Nop. */ +} + /* Callback to be used when calling fork_inferior, responsible for actually initiating the tracing of the inferior. */ @@ -984,7 +972,7 @@ linux_process_target::create_inferior (const char *program, { maybe_disable_address_space_randomization restore_personality (cs.disable_randomization); - std::string str_program_args = stringify_argv (program_args); + std::string str_program_args = construct_inferior_arguments (program_args); pid = fork_inferior (program, str_program_args.c_str (), @@ -992,7 +980,7 @@ linux_process_target::create_inferior (const char *program, NULL, NULL, NULL, NULL); } - linux_add_process (pid, 0); + add_linux_process (pid, 0); ptid = ptid_t (pid, pid, 0); new_lwp = add_lwp (ptid); @@ -1022,11 +1010,8 @@ linux_process_target::post_create_inferior () } } -/* Attach to an inferior process. Returns 0 on success, ERRNO on - error. */ - int -linux_attach_lwp (ptid_t ptid) +linux_process_target::attach_lwp (ptid_t ptid) { struct lwp_info *new_lwp; int lwpid = ptid.lwp (); @@ -1123,7 +1108,7 @@ attach_proc_task_lwp_callback (ptid_t ptid) if (debug_threads) debug_printf ("Found new lwp %d\n", lwpid); - err = linux_attach_lwp (ptid); + err = the_linux_target->attach_lwp (ptid); /* Be quiet if we simply raced with the thread exiting. EPERM is returned if the thread's task still exists, and is marked @@ -1165,11 +1150,11 @@ linux_process_target::attach (unsigned long pid) ptid_t ptid = ptid_t (pid, pid, 0); int err; - proc = linux_add_process (pid, 1); + proc = add_linux_process (pid, 1); /* Attach to PID. We will check for other threads soon. */ - err = linux_attach_lwp (ptid); + err = attach_lwp (ptid); if (err != 0) { remove_process (proc); @@ -1477,10 +1462,8 @@ get_detach_signal (struct thread_info *thread) } } -/* Detach from LWP. */ - -static void -linux_detach_one_lwp (struct lwp_info *lwp) +void +linux_process_target::detach_one_lwp (lwp_info *lwp) { struct thread_info *thread = get_lwp_thread (lwp); int sig; @@ -1509,8 +1492,7 @@ linux_detach_one_lwp (struct lwp_info *lwp) regcache_invalidate_thread (thread); /* Finally, let it resume. */ - if (the_low_target.prepare_to_resume != NULL) - the_low_target.prepare_to_resume (lwp); + low_prepare_to_resume (lwp); } catch (const gdb_exception_error &ex) { @@ -1562,22 +1544,6 @@ linux_detach_one_lwp (struct lwp_info *lwp) delete_lwp (lwp); } -/* Callback for for_each_thread. Detaches from non-leader threads of a - given process. */ - -static void -linux_detach_lwp_callback (thread_info *thread) -{ - /* We don't actually detach from the thread group leader just yet. - If the thread group exits, we must reap the zombie clone lwps - before we're able to reap the leader. */ - if (thread->id.pid () == thread->id.lwp ()) - return; - - lwp_info *lwp = get_thread_lwp (thread); - linux_detach_one_lwp (lwp); -} - int linux_process_target::detach (process_info *process) { @@ -1604,10 +1570,20 @@ linux_process_target::detach (process_info *process) /* Detach from the clone lwps first. If the thread group exits just while we're detaching, we must reap the clone lwps before we're able to reap the leader. */ - for_each_thread (process->pid, linux_detach_lwp_callback); + for_each_thread (process->pid, [this] (thread_info *thread) + { + /* We don't actually detach from the thread group leader just yet. + If the thread group exits, we must reap the zombie clone lwps + before we're able to reap the leader. */ + if (thread->id.pid () == thread->id.lwp ()) + return; + + lwp_info *lwp = get_thread_lwp (thread); + detach_one_lwp (lwp); + }); main_lwp = find_lwp_pid (ptid_t (process->pid)); - linux_detach_one_lwp (main_lwp); + detach_one_lwp (main_lwp); mourn (process); @@ -1628,17 +1604,14 @@ linux_process_target::mourn (process_info *process) thread_db_mourn (process); #endif - for_each_thread (process->pid, [] (thread_info *thread) + for_each_thread (process->pid, [this] (thread_info *thread) { delete_lwp (get_thread_lwp (thread)); }); /* Freeing all private data. */ priv = process->priv; - if (the_low_target.delete_process != NULL) - the_low_target.delete_process (priv->arch_private); - else - gdb_assert (priv->arch_private == NULL); + low_delete_process (priv->arch_private); free (priv); process->priv = NULL; @@ -1706,7 +1679,7 @@ linux_process_target::thread_still_has_status_pending (thread_info *thread) #if !USE_SIGTRAP_SIGINFO else if (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT - && !(*the_low_target.breakpoint_at) (pc)) + && !low_breakpoint_at (pc)) { if (debug_threads) debug_printf ("previous SW breakpoint of %ld gone\n", @@ -1830,13 +1803,10 @@ iterate_over_lwps (ptid_t filter, return get_thread_lwp (thread); } -/* Detect zombie thread group leaders, and "exit" them. We can't reap - their exits until all other threads in the group have exited. */ - -static void -check_zombie_leaders (void) +void +linux_process_target::check_zombie_leaders () { - for_each_process ([] (process_info *proc) { + for_each_process ([this] (process_info *proc) { pid_t leader_pid = pid_of (proc); struct lwp_info *leader_lp; @@ -1989,29 +1959,29 @@ handle_tracepoints (struct lwp_info *lwp) return 0; } -/* Convenience wrapper. Returns information about LWP's fast tracepoint - collection status. */ - -static fast_tpoint_collect_result -linux_fast_tracepoint_collecting (struct lwp_info *lwp, - struct fast_tpoint_collect_status *status) +fast_tpoint_collect_result +linux_process_target::linux_fast_tracepoint_collecting + (lwp_info *lwp, fast_tpoint_collect_status *status) { CORE_ADDR thread_area; struct thread_info *thread = get_lwp_thread (lwp); - if (the_low_target.get_thread_area == NULL) - return fast_tpoint_collect_result::not_collecting; - /* Get the thread area address. This is used to recognize which thread is which when tracing with the in-process agent library. We don't read anything from the address, and treat it as opaque; it's the address itself that we assume is unique per-thread. */ - if ((*the_low_target.get_thread_area) (lwpid_of (thread), &thread_area) == -1) + if (low_get_thread_area (lwpid_of (thread), &thread_area) == -1) return fast_tpoint_collect_result::not_collecting; return fast_tracepoint_collecting (thread_area, lwp->stop_pc, status); } +int +linux_process_target::low_get_thread_area (int lwpid, CORE_ADDR *addrp) +{ + return -1; +} + bool linux_process_target::maybe_move_out_of_jump_pad (lwp_info *lwp, int *wstat) { @@ -2142,7 +2112,6 @@ linux_process_target::maybe_move_out_of_jump_pad (lwp_info *lwp, int *wstat) static void enqueue_one_deferred_signal (struct lwp_info *lwp, int *wstat) { - struct pending_signals *p_sig; struct thread_info *thread = get_lwp_thread (lwp); if (debug_threads) @@ -2151,13 +2120,9 @@ enqueue_one_deferred_signal (struct lwp_info *lwp, int *wstat) if (debug_threads) { - struct pending_signals *sig; - - for (sig = lwp->pending_signals_to_report; - sig != NULL; - sig = sig->prev) + for (const auto &sig : lwp->pending_signals_to_report) debug_printf (" Already queued %d\n", - sig->signal); + sig.signal); debug_printf (" (no more currently queued signals)\n"); } @@ -2167,32 +2132,24 @@ enqueue_one_deferred_signal (struct lwp_info *lwp, int *wstat) twice) */ if (WSTOPSIG (*wstat) < __SIGRTMIN) { - struct pending_signals *sig; - - for (sig = lwp->pending_signals_to_report; - sig != NULL; - sig = sig->prev) + for (const auto &sig : lwp->pending_signals_to_report) { - if (sig->signal == WSTOPSIG (*wstat)) + if (sig.signal == WSTOPSIG (*wstat)) { if (debug_threads) debug_printf ("Not requeuing already queued non-RT signal %d" " for LWP %ld\n", - sig->signal, + sig.signal, lwpid_of (thread)); return; } } } - p_sig = XCNEW (struct pending_signals); - p_sig->prev = lwp->pending_signals_to_report; - p_sig->signal = WSTOPSIG (*wstat); + lwp->pending_signals_to_report.emplace_back (WSTOPSIG (*wstat)); ptrace (PTRACE_GETSIGINFO, lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, - &p_sig->info); - - lwp->pending_signals_to_report = p_sig; + &lwp->pending_signals_to_report.back ().info); } /* Dequeue one signal from the "signals to report later when out of @@ -2203,20 +2160,16 @@ dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat) { struct thread_info *thread = get_lwp_thread (lwp); - if (lwp->pending_signals_to_report != NULL) + if (!lwp->pending_signals_to_report.empty ()) { - struct pending_signals **p_sig; - - p_sig = &lwp->pending_signals_to_report; - while ((*p_sig)->prev != NULL) - p_sig = &(*p_sig)->prev; + const pending_signal &p_sig = lwp->pending_signals_to_report.front (); - *wstat = W_STOPCODE ((*p_sig)->signal); - if ((*p_sig)->info.si_signo != 0) + *wstat = W_STOPCODE (p_sig.signal); + if (p_sig.info.si_signo != 0) ptrace (PTRACE_SETSIGINFO, lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, - &(*p_sig)->info); - free (*p_sig); - *p_sig = NULL; + &p_sig.info); + + lwp->pending_signals_to_report.pop_front (); if (debug_threads) debug_printf ("Reporting deferred signal %d for LWP %ld.\n", @@ -2224,13 +2177,9 @@ dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat) if (debug_threads) { - struct pending_signals *sig; - - for (sig = lwp->pending_signals_to_report; - sig != NULL; - sig = sig->prev) + for (const auto &sig : lwp->pending_signals_to_report) debug_printf (" Still queued %d\n", - sig->signal); + sig.signal); debug_printf (" (no more queued signals)\n"); } @@ -2241,46 +2190,33 @@ dequeue_one_deferred_signal (struct lwp_info *lwp, int *wstat) return 0; } -/* 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. */ - -static int -check_stopped_by_watchpoint (struct lwp_info *child) +bool +linux_process_target::check_stopped_by_watchpoint (lwp_info *child) { - if (the_low_target.stopped_by_watchpoint != NULL) - { - struct thread_info *saved_thread; + struct thread_info *saved_thread = current_thread; + current_thread = get_lwp_thread (child); - saved_thread = current_thread; - current_thread = get_lwp_thread (child); + if (low_stopped_by_watchpoint ()) + { + child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT; + child->stopped_data_address = low_stopped_data_address (); + } - if (the_low_target.stopped_by_watchpoint ()) - { - child->stop_reason = TARGET_STOPPED_BY_WATCHPOINT; + current_thread = saved_thread; - if (the_low_target.stopped_data_address != NULL) - child->stopped_data_address - = the_low_target.stopped_data_address (); - else - child->stopped_data_address = 0; - } + return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT; +} - current_thread = saved_thread; - } +bool +linux_process_target::low_stopped_by_watchpoint () +{ + return false; +} - return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT; +CORE_ADDR +linux_process_target::low_stopped_data_address () +{ + return 0; } /* Return the ptrace options that we want to try to enable. */ @@ -2518,19 +2454,17 @@ linux_process_target::filter_event (int lwpid, int wstat) return child; } -/* Return true if THREAD is doing hardware single step. */ - -static int -maybe_hw_step (struct thread_info *thread) +bool +linux_process_target::maybe_hw_step (thread_info *thread) { - if (can_hardware_single_step ()) - return 1; + if (supports_hardware_single_step ()) + return true; else { /* GDBserver must insert single-step breakpoint for software single step. */ gdb_assert (has_single_step_breakpoints (thread)); - return 0; + return false; } } @@ -2839,7 +2773,6 @@ unsuspend_all_lwps (struct lwp_info *except) }); } -static bool stuck_in_jump_pad_callback (thread_info *thread); static bool lwp_running (thread_info *thread); /* Stabilize threads (move out of jump pads). @@ -2875,7 +2808,10 @@ static bool lwp_running (thread_info *thread); void linux_process_target::stabilize_threads () { - thread_info *thread_stuck = find_thread (stuck_in_jump_pad_callback); + thread_info *thread_stuck = find_thread ([this] (thread_info *thread) + { + return stuck_in_jump_pad (thread); + }); if (thread_stuck != NULL) { @@ -2931,7 +2867,10 @@ linux_process_target::stabilize_threads () if (debug_threads) { - thread_stuck = find_thread (stuck_in_jump_pad_callback); + thread_stuck = find_thread ([this] (thread_info *thread) + { + return stuck_in_jump_pad (thread); + }); if (thread_stuck != NULL) debug_printf ("couldn't stabilize, LWP %ld got stuck in jump pad\n", @@ -2954,14 +2893,9 @@ ignore_event (struct target_waitstatus *ourstatus) return null_ptid; } -/* 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. */ - -static ptid_t -filter_exit_event (struct lwp_info *event_child, - struct target_waitstatus *ourstatus) +ptid_t +linux_process_target::filter_exit_event (lwp_info *event_child, + target_waitstatus *ourstatus) { client_state &cs = get_client_state (); struct thread_info *thread = get_lwp_thread (event_child); @@ -2990,29 +2924,26 @@ gdb_catching_syscalls_p (struct lwp_info *event_child) return !proc->syscalls_to_catch.empty (); } -/* Returns 1 if GDB is interested in the event_child syscall. - Only to be called when stopped reason is SYSCALL_SIGTRAP. */ - -static int -gdb_catch_this_syscall_p (struct lwp_info *event_child) +bool +linux_process_target::gdb_catch_this_syscall (lwp_info *event_child) { int sysno; struct thread_info *thread = get_lwp_thread (event_child); struct process_info *proc = get_thread_process (thread); if (proc->syscalls_to_catch.empty ()) - return 0; + return false; if (proc->syscalls_to_catch[0] == ANY_SYSCALL) - return 1; + return true; get_syscall_trapinfo (event_child, &sysno); for (int iter : proc->syscalls_to_catch) if (iter == sysno) - return 1; + return true; - return 0; + return false; } ptid_t @@ -3181,7 +3112,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus, event_child->stop_pc += increment_pc; low_set_pc (regcache, event_child->stop_pc); - if (!(*the_low_target.breakpoint_at) (event_child->stop_pc)) + if (!low_breakpoint_at (event_child->stop_pc)) event_child->stop_reason = TARGET_STOPPED_BY_NO_REASON; } } @@ -3196,7 +3127,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus, && (WSTOPSIG (w) == SIGTRAP || ((WSTOPSIG (w) == SIGILL || WSTOPSIG (w) == SIGSEGV) - && (*the_low_target.breakpoint_at) (event_child->stop_pc)))); + && low_breakpoint_at (event_child->stop_pc)))); if (maybe_internal_trap) { @@ -3355,7 +3286,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus, /* Check if GDB is interested in this syscall. */ if (WIFSTOPPED (w) && WSTOPSIG (w) == SYSCALL_SIGTRAP - && !gdb_catch_this_syscall_p (event_child)) + && !gdb_catch_this_syscall (event_child)) { if (debug_threads) { @@ -3508,7 +3439,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus, /* Remove the single-step breakpoints if any. Note that there isn't single-step breakpoint if we finished stepping over. */ - if (can_software_single_step () + if (supports_software_single_step () && has_single_step_breakpoints (current_thread)) { stop_all_lwps (0, event_child); @@ -3555,7 +3486,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus, /* Alright, we're going to report a stop. */ /* Remove single-step breakpoints. */ - if (can_software_single_step ()) + if (supports_software_single_step ()) { /* Remove single-step breakpoints or not. It it is true, stop all lwps, so that other threads won't hit the breakpoint in the @@ -3696,7 +3627,7 @@ linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus, if (event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT && !cs.swbreak_feature) { - int decr_pc = the_low_target.decr_pc_after_break; + int decr_pc = low_decr_pc_after_break (); if (decr_pc != 0) { @@ -3959,13 +3890,8 @@ linux_process_target::wait_for_sigstop () } } -/* 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. */ - -static bool -stuck_in_jump_pad_callback (thread_info *thread) +bool +linux_process_target::stuck_in_jump_pad (thread_info *thread) { struct lwp_info *lwp = get_thread_lwp (thread); @@ -4096,15 +4022,11 @@ linux_process_target::stop_all_lwps (int suspend, lwp_info *except) static void enqueue_pending_signal (struct lwp_info *lwp, int signal, siginfo_t *info) { - struct pending_signals *p_sig = XNEW (struct pending_signals); - - p_sig->prev = lwp->pending_signals; - p_sig->signal = signal; - if (info == NULL) - memset (&p_sig->info, 0, sizeof (siginfo_t)); + lwp->pending_signals.emplace_back (signal); + if (info == nullptr) + memset (&lwp->pending_signals.back ().info, 0, sizeof (siginfo_t)); else - memcpy (&p_sig->info, info, sizeof (siginfo_t)); - lwp->pending_signals = p_sig; + lwp->pending_signals.back ().info = *info; } void @@ -4116,7 +4038,7 @@ linux_process_target::install_software_single_step_breakpoints (lwp_info *lwp) scoped_restore save_current_thread = make_scoped_restore (¤t_thread); current_thread = thread; - std::vector next_pcs = the_low_target.get_next_pcs (regcache); + std::vector next_pcs = low_get_next_pcs (regcache); for (CORE_ADDR pc : next_pcs) set_single_step_breakpoint (pc, current_ptid); @@ -4127,11 +4049,11 @@ linux_process_target::single_step (lwp_info* lwp) { int step = 0; - if (can_hardware_single_step ()) + if (supports_hardware_single_step ()) { step = 1; } - else if (can_software_single_step ()) + else if (supports_software_single_step ()) { install_software_single_step_breakpoints (lwp); step = 0; @@ -4200,7 +4122,7 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step, inferior right now. */ if (signal != 0 && (lwp->status_pending_p - || lwp->pending_signals != NULL + || !lwp->pending_signals.empty () || !lwp_signal_can_be_delivered (lwp))) { enqueue_pending_signal (lwp, signal, info); @@ -4238,7 +4160,7 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step, debug_printf (" pending reinsert at 0x%s\n", paddress (lwp->bp_reinsert)); - if (can_hardware_single_step ()) + if (supports_hardware_single_step ()) { if (fast_tp_collecting == fast_tpoint_collect_result::not_collecting) { @@ -4267,7 +4189,7 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step, " single-stepping\n", lwpid_of (thread)); - if (can_hardware_single_step ()) + if (supports_hardware_single_step ()) step = 1; else { @@ -4309,21 +4231,16 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step, /* If we have pending signals, consume one if it can be delivered to the inferior. */ - if (lwp->pending_signals != NULL && lwp_signal_can_be_delivered (lwp)) + if (!lwp->pending_signals.empty () && lwp_signal_can_be_delivered (lwp)) { - struct pending_signals **p_sig; - - p_sig = &lwp->pending_signals; - while ((*p_sig)->prev != NULL) - p_sig = &(*p_sig)->prev; + const pending_signal &p_sig = lwp->pending_signals.front (); - signal = (*p_sig)->signal; - if ((*p_sig)->info.si_signo != 0) + signal = p_sig.signal; + if (p_sig.info.si_signo != 0) ptrace (PTRACE_SETSIGINFO, lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, - &(*p_sig)->info); + &p_sig.info); - free (*p_sig); - *p_sig = NULL; + lwp->pending_signals.pop_front (); } if (debug_threads) @@ -4331,8 +4248,7 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step, lwpid_of (thread), step ? "step" : "continue", signal, lwp->stop_expected ? "expected" : "not expected"); - if (the_low_target.prepare_to_resume != NULL) - the_low_target.prepare_to_resume (lwp); + low_prepare_to_resume (lwp); regcache_invalidate_thread (thread); errno = 0; @@ -4364,6 +4280,12 @@ linux_process_target::resume_one_lwp_throw (lwp_info *lwp, int step, lwp->stop_reason = TARGET_STOPPED_BY_NO_REASON; } +void +linux_process_target::low_prepare_to_resume (lwp_info *lwp) +{ + /* Nop. */ +} + /* Called when we try to resume a stopped LWP and that errors out. If the LWP is no longer in ptrace-stopped state (meaning it's zombie, or about to become), discard the error, clear any pending status @@ -4610,8 +4532,8 @@ linux_process_target::thread_needs_step_over (thread_info *thread) /* On software single step target, resume the inferior with signal rather than stepping over. */ - if (can_software_single_step () - && lwp->pending_signals != NULL + if (supports_software_single_step () + && !lwp->pending_signals.empty () && lwp_signal_can_be_delivered (lwp)) { if (debug_threads) @@ -4715,12 +4637,8 @@ linux_process_target::start_step_over (lwp_info *lwp) step_over_bkpt = thread->id; } -/* 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. */ - -static int -finish_step_over (struct lwp_info *lwp) +bool +linux_process_target::finish_step_over (lwp_info *lwp) { if (lwp->bp_reinsert != 0) { @@ -4743,7 +4661,7 @@ finish_step_over (struct lwp_info *lwp) and later not being able to explain it, because we were stepping over a breakpoint, and we hold all threads but LWP stopped while doing that. */ - if (!can_hardware_single_step ()) + if (!supports_hardware_single_step ()) { gdb_assert (has_single_step_breakpoints (current_thread)); delete_single_step_breakpoints (current_thread); @@ -4751,10 +4669,10 @@ finish_step_over (struct lwp_info *lwp) step_over_bkpt = null_ptid; current_thread = saved_thread; - return 1; + return true; } else - return 0; + return false; } void @@ -4832,7 +4750,7 @@ linux_process_target::resume_one_thread (thread_info *thread, midway through moving the LWP out of the jumppad, and we will report the pending signal as soon as that is finished. */ - if (lwp->pending_signals_to_report == NULL) + if (lwp->pending_signals_to_report.empty ()) send_sigstop (lwp); } @@ -5011,7 +4929,7 @@ linux_process_target::proceed_one_lwp (thread_info *thread, lwp_info *except) } if (thread->last_resume_kind == resume_stop - && lwp->pending_signals_to_report == NULL + && lwp->pending_signals_to_report.empty () && (lwp->collecting_fast_tracepoint == fast_tpoint_collect_result::not_collecting)) { @@ -5042,7 +4960,7 @@ linux_process_target::proceed_one_lwp (thread_info *thread, lwp_info *except) /* If resume_step is requested by GDB, install single-step breakpoints when the thread is about to be actually resumed if the single-step breakpoints weren't removed. */ - if (can_software_single_step () + if (supports_software_single_step () && !has_single_step_breakpoints (thread)) install_software_single_step_breakpoints (lwp); @@ -5419,10 +5337,7 @@ linux_process_target::fetch_register (const usrregs_info *usrregs, } } - if (the_low_target.supply_ptrace_register) - the_low_target.supply_ptrace_register (regcache, regno, buf); - else - supply_register (regcache, regno, buf); + low_supply_ptrace_register (regcache, regno, buf); } void @@ -5449,10 +5364,7 @@ linux_process_target::store_register (const usrregs_info *usrregs, buf = (char *) alloca (size); memset (buf, 0, size); - if (the_low_target.collect_ptrace_register) - the_low_target.collect_ptrace_register (regcache, regno, buf); - else - collect_register (regcache, regno, buf); + low_collect_ptrace_register (regcache, regno, buf); pid = lwpid_of (current_thread); for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE)) @@ -5481,6 +5393,20 @@ linux_process_target::store_register (const usrregs_info *usrregs, } #endif /* HAVE_LINUX_USRREGS */ +void +linux_process_target::low_collect_ptrace_register (regcache *regcache, + int regno, char *buf) +{ + collect_register (regcache, regno, buf); +} + +void +linux_process_target::low_supply_ptrace_register (regcache *regcache, + int regno, const char *buf) +{ + supply_register (regcache, regno, buf); +} + void linux_process_target::usr_fetch_inferior_registers (const regs_info *regs_info, regcache *regcache, @@ -5825,28 +5751,22 @@ linux_process_target::read_auxv (CORE_ADDR offset, unsigned char *myaddr, return n; } -/* These breakpoint and watchpoint related wrapper functions simply - pass on the function call if the target has registered a - corresponding function. */ - -bool -linux_process_target::supports_z_point_type (char z_type) -{ - return (the_low_target.supports_z_point_type != NULL - && the_low_target.supports_z_point_type (z_type)); -} - int linux_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr, int size, raw_breakpoint *bp) { if (type == raw_bkpt_type_sw) return insert_memory_breakpoint (bp); - else if (the_low_target.insert_point != NULL) - return the_low_target.insert_point (type, addr, size, bp); else - /* Unsupported (see target.h). */ - return 1; + return low_insert_point (type, addr, size, bp); +} + +int +linux_process_target::low_insert_point (raw_bkpt_type type, CORE_ADDR addr, + int size, raw_breakpoint *bp) +{ + /* Unsupported (see target.h). */ + return 1; } int @@ -5855,11 +5775,16 @@ linux_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr, { if (type == raw_bkpt_type_sw) return remove_memory_breakpoint (bp); - else if (the_low_target.remove_point != NULL) - return the_low_target.remove_point (type, addr, size, bp); else - /* Unsupported (see target.h). */ - return 1; + return low_remove_point (type, addr, size, bp); +} + +int +linux_process_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr, + int size, raw_breakpoint *bp) +{ + /* Unsupported (see target.h). */ + return 1; } /* Implement the stopped_by_sw_breakpoint target_ops @@ -5907,13 +5832,7 @@ linux_process_target::supports_stopped_by_hw_breakpoint () bool linux_process_target::supports_hardware_single_step () { - return can_hardware_single_step (); -} - -bool -linux_process_target::supports_software_single_step () -{ - return can_software_single_step (); + return true; } bool @@ -6026,16 +5945,11 @@ linux_process_target::qxfer_osdata (const char *annex, return linux_common_xfer_osdata (annex, readbuf, offset, len); } -/* Convert a native/host siginfo object, into/from the siginfo in the - layout of the inferiors' architecture. */ - -static void -siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction) +void +linux_process_target::siginfo_fixup (siginfo_t *siginfo, + gdb_byte *inf_siginfo, int direction) { - int done = 0; - - if (the_low_target.siginfo_fixup != NULL) - done = the_low_target.siginfo_fixup (siginfo, inf_siginfo, direction); + bool done = low_siginfo_fixup (siginfo, inf_siginfo, direction); /* If there was no callback, or the callback didn't do anything, then just do a straight memcpy. */ @@ -6048,6 +5962,13 @@ siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction) } } +bool +linux_process_target::low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, + int direction) +{ + return false; +} + bool linux_process_target::supports_qxfer_siginfo () { @@ -6299,12 +6220,16 @@ linux_process_target::supports_agent () bool linux_process_target::supports_range_stepping () { - if (can_software_single_step ()) + if (supports_software_single_step ()) return true; - if (*the_low_target.supports_range_stepping == NULL) - return false; - return (*the_low_target.supports_range_stepping) (); + return low_supports_range_stepping (); +} + +bool +linux_process_target::low_supports_range_stepping () +{ + return false; } bool @@ -6427,36 +6352,17 @@ linux_process_target::read_loadmap (const char *annex, CORE_ADDR offset, } #endif /* defined PT_GETDSBT || defined PTRACE_GETFDPIC */ -void -linux_process_target::process_qsupported (char **features, int count) -{ - if (the_low_target.process_qsupported != NULL) - the_low_target.process_qsupported (features, count); -} - bool linux_process_target::supports_catch_syscall () { - return (the_low_target.get_syscall_trapinfo != NULL + return (low_supports_catch_syscall () && linux_supports_tracesysgood ()); } -int -linux_process_target::get_ipa_tdesc_idx () -{ - if (the_low_target.get_ipa_tdesc_idx == NULL) - return 0; - - return (*the_low_target.get_ipa_tdesc_idx) (); -} - bool -linux_process_target::supports_tracepoints () +linux_process_target::low_supports_catch_syscall () { - if (*the_low_target.supports_tracepoints == NULL) - return false; - - return (*the_low_target.supports_tracepoints) (); + return false; } CORE_ADDR @@ -6524,44 +6430,6 @@ linux_process_target::done_accessing_memory () target_unpause_all (true); } -bool -linux_process_target::supports_fast_tracepoints () -{ - return the_low_target.install_fast_tracepoint_jump_pad != nullptr; -} - -int -linux_process_target::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_low_target.install_fast_tracepoint_jump_pad) - (tpoint, tpaddr, collector, lockaddr, orig_size, - jump_entry, trampoline, trampoline_size, - jjump_pad_insn, jjump_pad_insn_size, - adjusted_insn_addr, adjusted_insn_addr_end, - err); -} - -emit_ops * -linux_process_target::emit_ops () -{ - if (the_low_target.emit_ops != NULL) - return (*the_low_target.emit_ops) (); - else - return NULL; -} - -int -linux_process_target::get_min_fast_tracepoint_insn_len () -{ - return (*the_low_target.get_min_fast_tracepoint_insn_len) (); -} - /* Extract &phdr and num_phdr in the inferior. Return 0 on success. */ static int @@ -7230,39 +7098,6 @@ current_lwp_ptid (void) return ptid_of (current_thread); } -/* Implementation of the target_ops method "breakpoint_kind_from_pc". */ - -int -linux_process_target::breakpoint_kind_from_pc (CORE_ADDR *pcptr) -{ - if (the_low_target.breakpoint_kind_from_pc != NULL) - return (*the_low_target.breakpoint_kind_from_pc) (pcptr); - else - return process_stratum_target::breakpoint_kind_from_pc (pcptr); -} - -/* Implementation of the target_ops method "sw_breakpoint_from_kind". */ - -const gdb_byte * -linux_process_target::sw_breakpoint_from_kind (int kind, int *size) -{ - gdb_assert (the_low_target.sw_breakpoint_from_kind != NULL); - - return (*the_low_target.sw_breakpoint_from_kind) (kind, size); -} - -/* Implementation of the target_ops method - "breakpoint_kind_from_current_state". */ - -int -linux_process_target::breakpoint_kind_from_current_state (CORE_ADDR *pcptr) -{ - if (the_low_target.breakpoint_kind_from_current_state != NULL) - return (*the_low_target.breakpoint_kind_from_current_state) (pcptr); - else - return breakpoint_kind_from_pc (pcptr); -} - const char * linux_process_target::thread_name (ptid_t thread) {