X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdbserver%2Flinux-low.cc;h=2b522348201750a6946f638c92bd3b0ef52b36bf;hb=47f70aa7685c0a7fad4ca76964a4199a5b5edd1c;hp=8eca077180e34dec12c1ec5bc13f3df7b3ecbaf2;hpb=7582c77c1d2cab3f53b70697529c1644ceeb94a2;p=deliverable%2Fbinutils-gdb.git diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index 8eca077180..2b52234820 100644 --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc @@ -268,7 +268,6 @@ 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); @@ -317,6 +316,12 @@ linux_process_target::low_get_next_pcs (regcache *regcache) "implemented"); } +int +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. */ @@ -407,8 +412,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); @@ -417,31 +422,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); } -/* 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) { @@ -522,7 +548,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); @@ -566,8 +592,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) @@ -694,7 +719,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); @@ -780,8 +805,6 @@ get_syscall_trapinfo (struct lwp_info *lwp, int *sysno) current_thread = saved_thread; } -static int check_stopped_by_watchpoint (struct lwp_info *child); - bool linux_process_target::save_stop_reason (lwp_info *lwp) { @@ -796,7 +819,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; @@ -850,7 +873,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)) @@ -917,8 +940,8 @@ 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; @@ -928,12 +951,17 @@ add_lwp (ptid_t ptid) 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. */ @@ -990,7 +1018,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); @@ -1020,11 +1048,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 (); @@ -1121,7 +1146,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 @@ -1163,11 +1188,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); @@ -1475,10 +1500,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; @@ -1507,8 +1530,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) { @@ -1560,22 +1582,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) { @@ -1602,10 +1608,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); @@ -1626,17 +1642,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; @@ -1704,7 +1717,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", @@ -1828,13 +1841,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; @@ -2239,46 +2249,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. */ @@ -2952,14 +2949,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); @@ -3179,7 +3171,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; } } @@ -3194,7 +3186,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) { @@ -3694,7 +3686,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) { @@ -4329,8 +4321,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; @@ -4362,6 +4353,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 @@ -5417,10 +5414,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 @@ -5447,10 +5441,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)) @@ -5479,6 +5470,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, @@ -5823,28 +5828,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 @@ -5853,11 +5852,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 @@ -6018,16 +6022,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. */ @@ -6040,6 +6039,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 () { @@ -6419,13 +6425,6 @@ 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 () { @@ -6442,15 +6441,6 @@ linux_process_target::get_ipa_tdesc_idx () return (*the_low_target.get_ipa_tdesc_idx) (); } -bool -linux_process_target::supports_tracepoints () -{ - if (*the_low_target.supports_tracepoints == NULL) - return false; - - return (*the_low_target.supports_tracepoints) (); -} - CORE_ADDR linux_process_target::read_pc (regcache *regcache) {