X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdbserver%2Flinux-low.cc;h=9684922d1a1026a09cde6d43a55007a3947928ea;hb=013e3554b269aa1da0fcd478969f0df65341e50e;hp=fd225789347e46e46bb6b7f1788f971518ffbb49;hpb=d4807ea231eea599a474a9ad75a0552ef7217e1f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index fd22578934..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,17 +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; -} - bool linux_process_target::low_supports_breakpoints () { @@ -323,16 +305,6 @@ linux_process_target::low_decr_pc_after_break () return 0; } -/* Returns true if this target can support fast tracepoints. This - does not mean that the in-process agent has been loaded in the - inferior. */ - -static int -supports_fast_tracepoints (void) -{ - return the_low_target.install_fast_tracepoint_jump_pad != NULL; -} - /* True if LWP is stopped in its stepping range. */ static int @@ -343,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 }; @@ -413,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); @@ -423,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) { @@ -528,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); @@ -572,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) @@ -700,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); @@ -757,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); @@ -786,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) @@ -856,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)) @@ -923,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. */ @@ -988,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 (), @@ -996,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); @@ -1026,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 (); @@ -1127,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 @@ -1169,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); @@ -1481,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; @@ -1513,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) { @@ -1566,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) { @@ -1608,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); @@ -1632,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; @@ -1710,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", @@ -1834,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; @@ -1993,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) { @@ -2146,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) @@ -2155,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"); } @@ -2171,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 @@ -2207,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", @@ -2228,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"); } @@ -2245,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. */ @@ -2522,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; } } @@ -2843,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). @@ -2879,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) { @@ -2935,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", @@ -2958,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); @@ -2994,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 @@ -3185,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; } } @@ -3200,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) { @@ -3359,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) { @@ -3963,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); @@ -4100,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 @@ -4131,7 +4049,7 @@ linux_process_target::single_step (lwp_info* lwp) { int step = 0; - if (can_hardware_single_step ()) + if (supports_hardware_single_step ()) { step = 1; } @@ -4204,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); @@ -4242,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) { @@ -4271,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 { @@ -4313,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) @@ -4335,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; @@ -4368,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 @@ -4615,7 +4533,7 @@ 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 (supports_software_single_step () - && lwp->pending_signals != NULL + && !lwp->pending_signals.empty () && lwp_signal_can_be_delivered (lwp)) { if (debug_threads) @@ -4719,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) { @@ -4747,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); @@ -4755,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 @@ -4836,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); } @@ -5015,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)) { @@ -5423,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 @@ -5453,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)) @@ -5485,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, @@ -5829,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 @@ -5859,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 @@ -5911,7 +5832,7 @@ linux_process_target::supports_stopped_by_hw_breakpoint () bool linux_process_target::supports_hardware_single_step () { - return can_hardware_single_step (); + return true; } bool @@ -6024,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. */ @@ -6046,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,10 +6222,14 @@ linux_process_target::supports_range_stepping () { 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 @@ -6425,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 @@ -6522,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