diff options
author | Pedro Alves <palves@redhat.com> | 2010-05-02 00:47:34 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2010-05-02 00:47:34 +0000 |
commit | f9e39928dc25d4f8ec5cad87c6cea4cd5ef08f58 (patch) | |
tree | 630db2ced76156c381815d049c88d847b30506ab /gdb/gdbserver/thread-db.c | |
parent | 9dbc5bd27584aef258ea89fb41d21006f59dcfa5 (diff) | |
download | gdb-f9e39928dc25d4f8ec5cad87c6cea4cd5ef08f58.zip gdb-f9e39928dc25d4f8ec5cad87c6cea4cd5ef08f58.tar.gz gdb-f9e39928dc25d4f8ec5cad87c6cea4cd5ef08f58.tar.bz2 |
* linux-low.c (linux_kill_one_lwp): Assume the lwp is stopped.
(linux_kill): Stop all lwps here. Don't delete the main lwp here.
(linux_detach_one_lwp): Assume the lwp is stopped.
(any_thread_of): Delete.
(linux_detach): Stop all lwps here. Don't blindly delete all
breakpoints.
(delete_lwp_callback): New.
(linux_mourn): Delete all lwps of the process that is gone.
(linux_wait_1): Don't delete the last lwp of the process here.
* mem-break.h (mark_breakpoints_out): Declare.
* mem-break.c (mark_breakpoints_out): New.
(free_all_breakpoints): Use it.
* server.c (handle_target_event): If the process is gone, mark
breakpoints out.
* thread-db.c (struct thread_db) <create_bp>: New field.
(thread_db_enable_reporting): Fix prototype. Store a thread event
breakpoint reference in the thread_db struct.
(thread_db_load_search): Clear the thread_db object.
(try_thread_db_load_1): Ditto.
(switch_to_process): New.
(disable_thread_event_reporting): Use it.
(remove_thread_event_breakpoints): New.
(thread_db_detach, thread_db_mourn): Use it.
Diffstat (limited to 'gdb/gdbserver/thread-db.c')
-rw-r--r-- | gdb/gdbserver/thread-db.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c index 8e7d7a9..7dec30d 100644 --- a/gdb/gdbserver/thread-db.c +++ b/gdb/gdbserver/thread-db.c @@ -52,6 +52,16 @@ struct thread_db void *handle; #endif + /* Thread creation event breakpoint. The code at this location in + the child process will be called by the pthread library whenever + a new thread is created. By setting a special breakpoint at this + location, GDB can detect when a new thread is created. We obtain + this location via the td_ta_event_addr call. Note that if the + running kernel supports tracing clones, then we don't need to use + (and in fact don't use) this magic thread event breakpoint to + learn about threads. */ + struct breakpoint *td_create_bp; + /* Addresses of libthread_db functions. */ td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, td_thragent_t **ta); td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, @@ -205,7 +215,7 @@ thread_db_create_event (CORE_ADDR where) } static int -thread_db_enable_reporting () +thread_db_enable_reporting (void) { td_thr_events_t events; td_notify_t notify; @@ -239,8 +249,9 @@ thread_db_enable_reporting () thread_db_err_str (err)); return 0; } - set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr, - thread_db_create_event); + thread_db->td_create_bp + = set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr, + thread_db_create_event); return 1; } @@ -501,6 +512,8 @@ thread_db_load_search (void) if (proc->private->thread_db != NULL) fatal ("unexpected: proc->private->thread_db != NULL"); + memset (&tdb, 0, sizeof (tdb)); + tdb.td_ta_new_p = &td_ta_new; /* Attempt to open a connection to the thread library. */ @@ -544,6 +557,8 @@ try_thread_db_load_1 (void *handle) if (proc->private->thread_db != NULL) fatal ("unexpected: proc->private->thread_db != NULL"); + memset (&tdb, 0, sizeof (tdb)); + tdb.handle = handle; /* Initialize pointers to the dynamic library functions we will use. @@ -766,6 +781,16 @@ any_thread_of (struct inferior_list_entry *entry, void *args) return 0; } +static void +switch_to_process (struct process_info *proc) +{ + int pid = pid_of (proc); + + current_inferior = + (struct thread_info *) find_inferior (&all_threads, + any_thread_of, &pid); +} + /* Disconnect from libthread_db and free resources. */ static void @@ -785,15 +810,10 @@ disable_thread_event_reporting (struct process_info *proc) if (td_ta_clear_event_p != NULL) { - struct thread_info *saved_inferior; + struct thread_info *saved_inferior = current_inferior; td_thr_events_t events; - int pid; - pid = pid_of (proc); - saved_inferior = current_inferior; - current_inferior = - (struct thread_info *) find_inferior (&all_threads, - any_thread_of, &pid); + switch_to_process (proc); /* Set the process wide mask saying we aren't interested in any events anymore. */ @@ -805,10 +825,34 @@ disable_thread_event_reporting (struct process_info *proc) } } +static void +remove_thread_event_breakpoints (struct process_info *proc) +{ + struct thread_db *thread_db = proc->private->thread_db; + + if (thread_db->td_create_bp != NULL) + { + struct thread_info *saved_inferior = current_inferior; + + switch_to_process (proc); + + delete_breakpoint (thread_db->td_create_bp); + thread_db->td_create_bp = NULL; + + current_inferior = saved_inferior; + } +} + void thread_db_detach (struct process_info *proc) { - disable_thread_event_reporting (proc); + struct thread_db *thread_db = proc->private->thread_db; + + if (thread_db) + { + disable_thread_event_reporting (proc); + remove_thread_event_breakpoints (proc); + } } /* Disconnect from libthread_db and free resources. */ |