mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-01-07 12:30:32 +00:00
* inferiors.c (change_inferior_id): Add comment.
* linux-low.c (check_removed_breakpoint): Add an early prototype. Improve debug output. (linux_attach): Doc update. (linux_detach_one_process, linux_detach): Clean up before releasing each process. (send_sigstop, wait_for_sigstop): Improve comments and debug output. * linux-low.h (struct process_info): Doc improvement. * mem-break.c (delete_all_breakpoints): New. * mem-break.h (delete_all_breakpoints): New prototype. * thread-db.c (find_first_thread): New. (thread_db_create_event): Call it instead of thread_db_find_new_threads. Clean up unused variables. (maybe_attach_thread): Remove first thread handling. (thread_db_find_new_threads): Use find_first_thread. (thread_db_get_tls_address): Likewise.
This commit is contained in:
parent
741d6ea85b
commit
ae13219ef8
@ -1,3 +1,22 @@
|
||||
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* inferiors.c (change_inferior_id): Add comment.
|
||||
* linux-low.c (check_removed_breakpoint): Add an early
|
||||
prototype. Improve debug output.
|
||||
(linux_attach): Doc update.
|
||||
(linux_detach_one_process, linux_detach): Clean up before releasing
|
||||
each process.
|
||||
(send_sigstop, wait_for_sigstop): Improve comments and debug output.
|
||||
* linux-low.h (struct process_info): Doc improvement.
|
||||
* mem-break.c (delete_all_breakpoints): New.
|
||||
* mem-break.h (delete_all_breakpoints): New prototype.
|
||||
* thread-db.c (find_first_thread): New.
|
||||
(thread_db_create_event): Call it instead of
|
||||
thread_db_find_new_threads. Clean up unused variables.
|
||||
(maybe_attach_thread): Remove first thread handling.
|
||||
(thread_db_find_new_threads): Use find_first_thread.
|
||||
(thread_db_get_tls_address): Likewise.
|
||||
|
||||
2007-06-27 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* thread-db.c (thread_db_find_new_threads): Add prototype.
|
||||
|
@ -64,6 +64,11 @@ for_each_inferior (struct inferior_list *list,
|
||||
}
|
||||
}
|
||||
|
||||
/* When debugging a single-threaded program, the threads list (such as
|
||||
it is) is indexed by PID. When debugging a multi-threaded program,
|
||||
we index by TID. This ugly routine replaces the
|
||||
first-debugged-thread's PID with its TID. */
|
||||
|
||||
void
|
||||
change_inferior_id (struct inferior_list *list,
|
||||
unsigned long new_id)
|
||||
|
@ -68,6 +68,7 @@ static void linux_resume_one_process (struct inferior_list_entry *entry,
|
||||
static void linux_resume (struct thread_resume *resume_info);
|
||||
static void stop_all_processes (void);
|
||||
static int linux_wait_for_event (struct thread_info *child);
|
||||
static int check_removed_breakpoint (struct process_info *event_child);
|
||||
|
||||
struct pending_signals
|
||||
{
|
||||
@ -224,7 +225,8 @@ linux_attach (unsigned long pid)
|
||||
|
||||
linux_attach_lwp (pid, pid);
|
||||
|
||||
/* Don't ignore the initial SIGSTOP if we just attached to this process. */
|
||||
/* Don't ignore the initial SIGSTOP if we just attached to this process.
|
||||
It will be collected by wait shortly. */
|
||||
process = (struct process_info *) find_inferior_id (&all_processes, pid);
|
||||
process->stop_expected = 0;
|
||||
|
||||
@ -286,13 +288,36 @@ linux_detach_one_process (struct inferior_list_entry *entry)
|
||||
struct thread_info *thread = (struct thread_info *) entry;
|
||||
struct process_info *process = get_thread_process (thread);
|
||||
|
||||
/* Make sure the process isn't stopped at a breakpoint that's
|
||||
no longer there. */
|
||||
check_removed_breakpoint (process);
|
||||
|
||||
/* If this process is stopped but is expecting a SIGSTOP, then make
|
||||
sure we take care of that now. This isn't absolutely guaranteed
|
||||
to collect the SIGSTOP, but is fairly likely to. */
|
||||
if (process->stop_expected)
|
||||
{
|
||||
/* Clear stop_expected, so that the SIGSTOP will be reported. */
|
||||
process->stop_expected = 0;
|
||||
if (process->stopped)
|
||||
linux_resume_one_process (&process->head, 0, 0, NULL);
|
||||
linux_wait_for_event (thread);
|
||||
}
|
||||
|
||||
/* Flush any pending changes to the process's registers. */
|
||||
regcache_invalidate_one ((struct inferior_list_entry *)
|
||||
get_process_thread (process));
|
||||
|
||||
/* Finally, let it resume. */
|
||||
ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
linux_detach (void)
|
||||
{
|
||||
delete_all_breakpoints ();
|
||||
for_each_inferior (&all_threads, linux_detach_one_process);
|
||||
clear_inferiors ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -332,7 +357,8 @@ check_removed_breakpoint (struct process_info *event_child)
|
||||
return 0;
|
||||
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Checking for breakpoint.\n");
|
||||
fprintf (stderr, "Checking for breakpoint in process %ld.\n",
|
||||
event_child->lwpid);
|
||||
|
||||
saved_inferior = current_inferior;
|
||||
current_inferior = get_process_thread (event_child);
|
||||
@ -345,7 +371,8 @@ check_removed_breakpoint (struct process_info *event_child)
|
||||
if (stop_pc != event_child->pending_stop_pc)
|
||||
{
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Ignoring, PC was changed.\n");
|
||||
fprintf (stderr, "Ignoring, PC was changed. Old PC was 0x%08llx\n",
|
||||
event_child->pending_stop_pc);
|
||||
|
||||
event_child->pending_is_breakpoint = 0;
|
||||
current_inferior = saved_inferior;
|
||||
@ -817,6 +844,13 @@ send_sigstop (struct inferior_list_entry *entry)
|
||||
send another. */
|
||||
if (process->stop_expected)
|
||||
{
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Have pending sigstop for process %ld\n",
|
||||
process->lwpid);
|
||||
|
||||
/* We clear the stop_expected flag so that wait_for_sigstop
|
||||
will receive the SIGSTOP event (instead of silently resuming and
|
||||
waiting again). It'll be reset below. */
|
||||
process->stop_expected = 0;
|
||||
return;
|
||||
}
|
||||
@ -852,7 +886,9 @@ wait_for_sigstop (struct inferior_list_entry *entry)
|
||||
&& WSTOPSIG (wstat) != SIGSTOP)
|
||||
{
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Stopped with non-sigstop signal\n");
|
||||
fprintf (stderr, "Process %ld (thread %ld) "
|
||||
"stopped with non-sigstop status %06x\n",
|
||||
process->lwpid, process->tid, wstat);
|
||||
process->status_pending_p = 1;
|
||||
process->status_pending = wstat;
|
||||
process->stop_expected = 1;
|
||||
|
@ -92,8 +92,12 @@ struct process_info
|
||||
unsigned long lwpid;
|
||||
unsigned long tid;
|
||||
|
||||
/* If this flag is set, the next SIGSTOP will be ignored (the process will
|
||||
be immediately resumed). */
|
||||
/* If this flag is set, the next SIGSTOP will be ignored (the
|
||||
process will be immediately resumed). This means that either we
|
||||
sent the SIGSTOP to it ourselves and got some other pending event
|
||||
(so the SIGSTOP is still pending), or that we stopped the
|
||||
inferior implicitly via PTRACE_ATTACH and have not waited for it
|
||||
yet. */
|
||||
int stop_expected;
|
||||
|
||||
/* If this flag is set, the process is known to be stopped right now (stop
|
||||
|
@ -283,3 +283,12 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
|
||||
memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete all breakpoints. */
|
||||
|
||||
void
|
||||
delete_all_breakpoints (void)
|
||||
{
|
||||
while (breakpoints)
|
||||
delete_breakpoint (breakpoints);
|
||||
}
|
||||
|
@ -72,4 +72,8 @@ void check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len);
|
||||
|
||||
void set_breakpoint_data (const unsigned char *bp_data, int bp_len);
|
||||
|
||||
/* Delete all breakpoints. */
|
||||
|
||||
void delete_all_breakpoints (void);
|
||||
|
||||
#endif /* MEM_BREAK_H */
|
||||
|
@ -41,7 +41,7 @@ static struct ps_prochandle proc_handle;
|
||||
/* Connection to the libthread_db library. */
|
||||
static td_thragent_t *thread_agent;
|
||||
|
||||
static void thread_db_find_new_threads (void);
|
||||
static int find_first_thread (void);
|
||||
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
|
||||
|
||||
static char *
|
||||
@ -135,15 +135,11 @@ thread_db_create_event (CORE_ADDR where)
|
||||
{
|
||||
td_event_msg_t msg;
|
||||
td_err_e err;
|
||||
struct inferior_linux_data *tdata;
|
||||
struct thread_info *inferior;
|
||||
struct process_info *process;
|
||||
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Thread creation event.\n");
|
||||
|
||||
tdata = inferior_target_data (current_inferior);
|
||||
|
||||
/* FIXME: This assumes we don't get another event.
|
||||
In the LinuxThreads implementation, this is safe,
|
||||
because all events come from the manager thread
|
||||
@ -156,10 +152,9 @@ thread_db_create_event (CORE_ADDR where)
|
||||
/* If we do not know about the main thread yet, this would be a good time to
|
||||
find it. We need to do this to pick up the main thread before any newly
|
||||
created threads. */
|
||||
inferior = (struct thread_info *) all_threads.head;
|
||||
process = get_thread_process (inferior);
|
||||
process = get_thread_process (current_inferior);
|
||||
if (process->thread_known == 0)
|
||||
thread_db_find_new_threads ();
|
||||
find_first_thread ();
|
||||
|
||||
/* msg.event == TD_EVENT_CREATE */
|
||||
|
||||
@ -230,6 +225,66 @@ thread_db_enable_reporting ()
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
find_first_thread (void)
|
||||
{
|
||||
td_thrhandle_t th;
|
||||
td_thrinfo_t ti;
|
||||
td_err_e err;
|
||||
struct thread_info *inferior;
|
||||
struct process_info *process;
|
||||
|
||||
inferior = (struct thread_info *) all_threads.head;
|
||||
process = get_thread_process (inferior);
|
||||
if (process->thread_known)
|
||||
return 1;
|
||||
|
||||
/* Get information about the one thread we know we have. */
|
||||
err = td_ta_map_lwp2thr (thread_agent, process->lwpid, &th);
|
||||
if (err != TD_OK)
|
||||
error ("Cannot get first thread handle: %s", thread_db_err_str (err));
|
||||
|
||||
err = td_thr_get_info (&th, &ti);
|
||||
if (err != TD_OK)
|
||||
error ("Cannot get first thread info: %s", thread_db_err_str (err));
|
||||
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Found first thread %ld (LWP %d)\n",
|
||||
ti.ti_tid, ti.ti_lid);
|
||||
|
||||
if (process->lwpid != ti.ti_lid)
|
||||
fatal ("PID mismatch! Expected %ld, got %ld",
|
||||
(long) process->lwpid, (long) ti.ti_lid);
|
||||
|
||||
/* If the new thread ID is zero, a final thread ID will be available
|
||||
later. Do not enable thread debugging yet. */
|
||||
if (ti.ti_tid == 0)
|
||||
{
|
||||
err = td_thr_event_enable (&th, 1);
|
||||
if (err != TD_OK)
|
||||
error ("Cannot enable thread event reporting for %d: %s",
|
||||
ti.ti_lid, thread_db_err_str (err));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Switch to indexing the threads list by TID. */
|
||||
change_inferior_id (&all_threads, ti.ti_tid);
|
||||
|
||||
new_thread_notify (ti.ti_tid);
|
||||
|
||||
process->tid = ti.ti_tid;
|
||||
process->lwpid = ti.ti_lid;
|
||||
process->thread_known = 1;
|
||||
process->th = th;
|
||||
|
||||
err = td_thr_event_enable (&th, 1);
|
||||
if (err != TD_OK)
|
||||
error ("Cannot enable thread event reporting for %d: %s",
|
||||
ti.ti_lid, thread_db_err_str (err));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
|
||||
{
|
||||
@ -237,36 +292,6 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
|
||||
struct thread_info *inferior;
|
||||
struct process_info *process;
|
||||
|
||||
/* If we are attaching to our first thread, things are a little
|
||||
different. */
|
||||
if (all_threads.head == all_threads.tail)
|
||||
{
|
||||
inferior = (struct thread_info *) all_threads.head;
|
||||
process = get_thread_process (inferior);
|
||||
|
||||
if (process->thread_known == 0)
|
||||
{
|
||||
/* If the new thread ID is zero, a final thread ID will be
|
||||
available later. Do not enable thread debugging yet. */
|
||||
if (ti_p->ti_tid == 0)
|
||||
{
|
||||
err = td_thr_event_enable (th_p, 1);
|
||||
if (err != TD_OK)
|
||||
error ("Cannot enable thread event reporting for %d: %s",
|
||||
ti_p->ti_lid, thread_db_err_str (err));
|
||||
return;
|
||||
}
|
||||
|
||||
if (process->lwpid != ti_p->ti_lid)
|
||||
fatal ("PID mismatch! Expected %ld, got %ld",
|
||||
(long) process->lwpid, (long) ti_p->ti_lid);
|
||||
|
||||
/* Switch to indexing the threads list by TID. */
|
||||
change_inferior_id (&all_threads, ti_p->ti_tid);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
inferior = (struct thread_info *) find_inferior_id (&all_threads,
|
||||
ti_p->ti_tid);
|
||||
if (inferior != NULL)
|
||||
@ -287,7 +312,6 @@ maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
|
||||
|
||||
process = inferior_target_data (inferior);
|
||||
|
||||
found:
|
||||
new_thread_notify (ti_p->ti_tid);
|
||||
|
||||
process->tid = ti_p->ti_tid;
|
||||
@ -325,6 +349,12 @@ thread_db_find_new_threads (void)
|
||||
{
|
||||
td_err_e err;
|
||||
|
||||
/* This function is only called when we first initialize thread_db.
|
||||
First locate the initial thread. If it is not ready for
|
||||
debugging yet, then stop. */
|
||||
if (find_first_thread () == 0)
|
||||
return;
|
||||
|
||||
/* Iterate over all user-space threads to discover new threads. */
|
||||
err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
|
||||
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
|
||||
@ -359,7 +389,7 @@ thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
|
||||
|
||||
process = get_thread_process (thread);
|
||||
if (!process->thread_known)
|
||||
thread_db_find_new_threads ();
|
||||
find_first_thread ();
|
||||
if (!process->thread_known)
|
||||
return TD_NOTHR;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user