diff options
Diffstat (limited to 'linuxthreads_db')
-rw-r--r-- | linuxthreads_db/ChangeLog | 28 | ||||
-rw-r--r-- | linuxthreads_db/td_ta_event_addr.c | 45 | ||||
-rw-r--r-- | linuxthreads_db/td_ta_new.c | 11 | ||||
-rw-r--r-- | linuxthreads_db/td_ta_set_event.c | 37 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_event_enable.c | 19 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_event_getmsg.c | 34 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_getfpregs.c | 8 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_getgregs.c | 8 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_set_event.c | 18 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_setfpregs.c | 6 | ||||
-rw-r--r-- | linuxthreads_db/td_thr_setgregs.c | 6 | ||||
-rw-r--r-- | linuxthreads_db/thread_db.h | 24 | ||||
-rw-r--r-- | linuxthreads_db/thread_dbP.h | 3 |
13 files changed, 211 insertions, 36 deletions
diff --git a/linuxthreads_db/ChangeLog b/linuxthreads_db/ChangeLog index e7dd8f6162..723f9a4650 100644 --- a/linuxthreads_db/ChangeLog +++ b/linuxthreads_db/ChangeLog @@ -1,16 +1,28 @@ +1999-11-02 Ulrich Drepper <drepper@cygnus.com> + + * td_ta_new.c: Don't test for __pthread_threads_debug. Get address + of __pthread_threads_events and fail if this is not possible. + * td_ta_event_addr.c: Implement. + * td_thr_event_enable.c: Implement. + * td_thr_event_getmsg.c: Implement. + * td_thr_set_event.c: Implement. + * td_ta_set_event.c: New file. + * thread_db.h (td_eventbuf_t): Define. + Declare td_ta_set_event. + * thread_dbP.h (struct td_thragent): Add pthread_threads_eventsp. + + * td_thr_getfpregs.c: For terminated threads return empty structure. + * td_thr_getgregs.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + 1999-11-01 Ulrich Drepper <drepper@cygnus.com> - * sysdeps/unix/sysv/linux/alpha/sys/procfs.h: Add more pr* types used - by the debugger. - * sysdeps/unix/sysv/linux/arm/sys/procfs.h: Likewise. - * sysdeps/unix/sysv/linux/i386/sys/procfs.h: Likewise. - * sysdeps/unix/sysv/linux/mips/sys/procfs.h: Likewise. - * sysdeps/unix/sysv/linux/powerpc/sys/procfs.h: Likewise. - * sysdeps/unix/sysv/linux/sys/procfs.h: Likewise. * thread_db.h: Shuffle types around to make things work for gdb. * thread_dbP.h: Include proc_service.h before thread_db.h. - * td_ta_new.c: It's TD_NOLIBTHREAD, not TD_LIBTHREAD. + * thread_db.h: It's TD_NOLIBTHREAD, not TD_LIBTHREAD. + * td_ta_new.c: Likewise. 1999-10-14 Ulrich Drepper <drepper@cygnus.com> diff --git a/linuxthreads_db/td_ta_event_addr.c b/linuxthreads_db/td_ta_event_addr.c index 6d6d4a850b..4edd54c55d 100644 --- a/linuxthreads_db/td_ta_event_addr.c +++ b/linuxthreads_db/td_ta_event_addr.c @@ -18,13 +18,54 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <gnu/lib-names.h> + #include "thread_dbP.h" td_err_e td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr) { - /* XXX We have to figure out what has to be done. */ + td_err_e res = TD_NOEVENT; + const char *symbol = NULL; + LOG (__FUNCTION__); - return TD_NOCAPAB; + + switch (event) + { + case TD_CREATE: + symbol = "__linuxthreads_create_event"; + break; + + case TD_DEATH: + symbol = "__linuxthreads_death_event"; + break; + + case TD_REAP: + symbol = "__linuxthreads_reap_event"; + break; + + default: + /* Event cannot be handled. */ + break; + } + + /* Now get the address. */ + if (symbol != NULL) + { + psaddr_t taddr; + + if (ps_pglobal_lookup (ta->ph, LIBPTHREAD_SO, symbol, &taddr) == PS_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + + res = TD_OK; + } + else + res = TD_ERR; + } + + return res; } diff --git a/linuxthreads_db/td_ta_new.c b/linuxthreads_db/td_ta_new.c index 8b22b75ab3..eeaf0cbf51 100644 --- a/linuxthreads_db/td_ta_new.c +++ b/linuxthreads_db/td_ta_new.c @@ -32,9 +32,11 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) LOG (__FUNCTION__); - /* See whether the library contains the necessary symbols. */ - if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, "__pthread_threads_debug", - &addr) != PS_OK) + /* Get the global event mask. This is one of the variables which + are new in the thread library to enable debugging. If it is + not available we cannot debug. */ + if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, + "__pthread_threads_events", &addr) != PS_OK) return TD_NOLIBTHREAD; /* Fill in the appropriate information. */ @@ -46,6 +48,9 @@ td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) back into the debugger. */ (*ta)->ph = ps; + /* Remember the address. */ + (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr; + /* See whether the library contains the necessary symbols. */ if (ps_pglobal_lookup (ps, LIBPTHREAD_SO, "__pthread_handles", &addr) != PS_OK) diff --git a/linuxthreads_db/td_ta_set_event.c b/linuxthreads_db/td_ta_set_event.c new file mode 100644 index 0000000000..10adbdf04f --- /dev/null +++ b/linuxthreads_db/td_ta_set_event.c @@ -0,0 +1,37 @@ +/* Globally enable events. + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + LOG (__FUNCTION__); + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + event, sizeof (td_thrhandle_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/linuxthreads_db/td_thr_event_enable.c b/linuxthreads_db/td_thr_event_enable.c index d6db6a76ca..79e7d3a2aa 100644 --- a/linuxthreads_db/td_thr_event_enable.c +++ b/linuxthreads_db/td_thr_event_enable.c @@ -1,4 +1,4 @@ -/* Enable event reporting. +/* Enable event process-wide. Copyright (C) 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. @@ -18,13 +18,24 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <stddef.h> + #include "thread_dbP.h" td_err_e -td_thr_event_enable (const td_thrhandle_t *th, int event) +td_thr_event_enable (th, onoff) + const td_thrhandle_t *th; + int onoff; { - /* XXX We have to figure out what has to be done. */ LOG (__FUNCTION__); - return TD_NOCAPAB; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_report_events)), + &onoff, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; } diff --git a/linuxthreads_db/td_thr_event_getmsg.c b/linuxthreads_db/td_thr_event_getmsg.c index 0fa4cd6fbe..4812ece4dd 100644 --- a/linuxthreads_db/td_thr_event_getmsg.c +++ b/linuxthreads_db/td_thr_event_getmsg.c @@ -18,13 +18,43 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <stddef.h> +#include <string.h> + #include "thread_dbP.h" td_err_e td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) { - /* XXX We have to figure out what has to be done. */ + td_eventbuf_t event; + LOG (__FUNCTION__); - return TD_NOCAPAB; + + /* Read the even structure from the target. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; } diff --git a/linuxthreads_db/td_thr_getfpregs.c b/linuxthreads_db/td_thr_getfpregs.c index 33bd95ee30..e6635d2644 100644 --- a/linuxthreads_db/td_thr_getfpregs.c +++ b/linuxthreads_db/td_thr_getfpregs.c @@ -28,12 +28,16 @@ td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) LOG (__FUNCTION__); - /* We have to get the PID for this thread. */ + /* We have to get the state and the PID for this thread. */ if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, sizeof (struct _pthread_descr_struct)) != PS_OK) return TD_ERR; - if (ps_lgetfpregs (th->th_ta_p->ph, pds.p_pid, regset) != PS_OK) + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else if (ps_lgetfpregs (th->th_ta_p->ph, pds.p_pid, regset) != PS_OK) return TD_ERR; return TD_OK; diff --git a/linuxthreads_db/td_thr_getgregs.c b/linuxthreads_db/td_thr_getgregs.c index e8a87b1bcc..549c7d8b83 100644 --- a/linuxthreads_db/td_thr_getgregs.c +++ b/linuxthreads_db/td_thr_getgregs.c @@ -28,12 +28,16 @@ td_thr_getgregs (const td_thrhandle_t *th, prgregset_t gregs) LOG (__FUNCTION__); - /* We have to get the PID for this thread. */ + /* We have to get the state and the PID for this thread. */ if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, sizeof (struct _pthread_descr_struct)) != PS_OK) return TD_ERR; - if (ps_lgetregs (th->th_ta_p->ph, pds.p_pid, gregs) != PS_OK) + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (gregs, '\0', sizeof (gregs)); + /* Otherwise get the register content through the callback. */ + else if (ps_lgetregs (th->th_ta_p->ph, pds.p_pid, gregs) != PS_OK) return TD_ERR; return TD_OK; diff --git a/linuxthreads_db/td_thr_set_event.c b/linuxthreads_db/td_thr_set_event.c index 9454309b22..e6b6cbc862 100644 --- a/linuxthreads_db/td_thr_set_event.c +++ b/linuxthreads_db/td_thr_set_event.c @@ -18,13 +18,25 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <stddef.h> + #include "thread_dbP.h" td_err_e -td_thr_set_event (const td_thrhandle_t *th, td_thr_events_t *event) +td_thr_set_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; { - /* XXX We have to figure out what has to be done. */ LOG (__FUNCTION__); - return TD_NOCAPAB; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + event, sizeof (td_thrhandle_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; } diff --git a/linuxthreads_db/td_thr_setfpregs.c b/linuxthreads_db/td_thr_setfpregs.c index a18e1edc1e..0c426b3d36 100644 --- a/linuxthreads_db/td_thr_setfpregs.c +++ b/linuxthreads_db/td_thr_setfpregs.c @@ -28,12 +28,14 @@ td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) LOG (__FUNCTION__); - /* We have to get the PID for this thread. */ + /* We have to get the state and the PID for this thread. */ if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, sizeof (struct _pthread_descr_struct)) != PS_OK) return TD_ERR; - if (ps_lsetfpregs (th->th_ta_p->ph, pds.p_pid, fpregs) != PS_OK) + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0 + && ps_lsetfpregs (th->th_ta_p->ph, pds.p_pid, fpregs) != PS_OK) return TD_ERR; return TD_OK; diff --git a/linuxthreads_db/td_thr_setgregs.c b/linuxthreads_db/td_thr_setgregs.c index 1de2d3c554..72f95b1ca7 100644 --- a/linuxthreads_db/td_thr_setgregs.c +++ b/linuxthreads_db/td_thr_setgregs.c @@ -28,12 +28,14 @@ td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) LOG (__FUNCTION__); - /* We have to get the PID for this thread. */ + /* We have to get the state and the PID for this thread. */ if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, sizeof (struct _pthread_descr_struct)) != PS_OK) return TD_ERR; - if (ps_lsetregs (th->th_ta_p->ph, pds.p_pid, gregs) != PS_OK) + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0 + && ps_lsetregs (th->th_ta_p->ph, pds.p_pid, gregs) != PS_OK) return TD_ERR; return TD_OK; diff --git a/linuxthreads_db/thread_db.h b/linuxthreads_db/thread_db.h index 312237ae23..8e33a06ee8 100644 --- a/linuxthreads_db/thread_db.h +++ b/linuxthreads_db/thread_db.h @@ -200,6 +200,14 @@ typedef struct td_event_msg } msg; } td_event_msg_t; +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + /* Gathered statistics about the process. */ typedef struct td_ta_stats @@ -228,10 +236,10 @@ typedef pthread_key_t thread_key_t; /* Callback for iteration over threads. */ -typedef int td_thr_iter_f __P ((const td_thrhandle_t *, void *)); +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); /* Callback for iteration over thread local data. */ -typedef int td_key_iter_f __P ((thread_key_t, void (*) (void *), void *)); +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); @@ -323,6 +331,10 @@ extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, td_event_e __event, td_notify_t *__ptr); +/* Enable EVENT for all threads. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + /* Set suggested concurrency level for process associated with TA. */ extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); @@ -348,11 +360,11 @@ extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, /* Retrieve floating-point register contents of process running thread TH. */ extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, - fpregset_t *__regset); + prfpregset_t *__regset); /* Retrieve general register contents of process running thread TH. */ extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, - gregset_t __gregs); + prgregset_t __gregs); /* Retrieve extended register contents of process running thread TH. */ extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); @@ -362,11 +374,11 @@ extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); /* Set floating-point register contents of process running thread TH. */ extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, - const fpregset_t *__fpregs); + const prfpregset_t *__fpregs); /* Set general register contents of process running thread TH. */ extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, - gregset_t __gregs); + prgregset_t __gregs); /* Set extended register contents of process running thread TH. */ extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, diff --git a/linuxthreads_db/thread_dbP.h b/linuxthreads_db/thread_dbP.h index 0fd1c11a28..5c7fcde28a 100644 --- a/linuxthreads_db/thread_dbP.h +++ b/linuxthreads_db/thread_dbP.h @@ -38,6 +38,9 @@ struct td_thragent /* Sizeof struct _pthread_descr_struct. */ int sizeof_descr; + + /* Pointer to the `__pthread_threads_events' variable in the target. */ + psaddr_t pthread_threads_eventsp; }; |