Back to index

glibc  2.9
td_ta_new.c
Go to the documentation of this file.
00001 /* Attach to target process.
00002    Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <stddef.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <version.h>
00025 
00026 #include "thread_dbP.h"
00027 
00028 
00029 /* Datatype for the list of known thread agents.  Normally there will
00030    be exactly one so we don't spend much though on making it fast.  */
00031 struct agent_list *__td_agent_list;
00032 
00033 
00034 td_err_e
00035 td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
00036 {
00037   psaddr_t addr;
00038   psaddr_t versaddr;
00039   char versbuf[sizeof (VERSION)];
00040   struct agent_list *elemp;
00041 
00042   LOG ("td_ta_new");
00043 
00044   /* Get the global event mask.  This is one of the variables which
00045      are new in the thread library to enable debugging.  If it is
00046      not available we cannot debug.  */
00047   if (td_lookup (ps, PTHREAD_THREADS_EVENTS, &addr) != PS_OK)
00048     return TD_NOLIBTHREAD;
00049 
00050   /* Check whether the versions match.  */
00051   if (td_lookup (ps, LINUXTHREADS_VERSION, &versaddr) != PS_OK)
00052     return TD_VERSION;
00053   if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK)
00054     return TD_ERR;
00055 
00056   versbuf[sizeof (versbuf) - 1] = '\0';
00057   if (strcmp (versbuf, VERSION) != 0)
00058     /* Not the right version.  */
00059     return TD_VERSION;
00060 
00061   /* Fill in the appropriate information.  */
00062   *ta = (td_thragent_t *) malloc (sizeof (td_thragent_t));
00063   if (*ta == NULL)
00064     return TD_MALLOC;
00065 
00066   /* Store the proc handle which we will pass to the callback functions
00067      back into the debugger.  */
00068   (*ta)->ph = ps;
00069 
00070   /* Remember the address.  */
00071   (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr;
00072 
00073   /* Get the pointer to the variable pointing to the thread descriptor
00074      with the last event.  */
00075   if (td_lookup (ps, PTHREAD_LAST_EVENT, &(*ta)->pthread_last_event) != PS_OK)
00076     {
00077     free_return:
00078       free (*ta);
00079       return TD_ERR;
00080     }
00081 
00082   /* Get the pointer to the variable containing the number of active
00083      threads.  */
00084   if (td_lookup (ps, PTHREAD_HANDLES_NUM, &(*ta)->pthread_handles_num)
00085       != PS_OK)
00086     goto free_return;
00087 
00088   /* See whether the library contains the necessary symbols.  */
00089   if (td_lookup (ps, PTHREAD_HANDLES, &addr) != PS_OK)
00090     goto free_return;
00091 
00092   (*ta)->handles = (struct pthread_handle_struct *) addr;
00093 
00094 
00095   if (td_lookup (ps, PTHREAD_KEYS, &addr) != PS_OK)
00096     goto free_return;
00097 
00098   /* Cast to the right type.  */
00099   (*ta)->keys = (struct pthread_key_struct *) addr;
00100 
00101   /* Find out about the maximum number of threads.  Old implementations
00102      don't provide this information.  In this case we assume that the
00103      debug  library is compiled with the same values.  */
00104   if (td_lookup (ps, LINUXTHREADS_PTHREAD_THREADS_MAX, &addr) != PS_OK)
00105     (*ta)->pthread_threads_max = PTHREAD_THREADS_MAX;
00106   else
00107     {
00108       if (ps_pdread (ps, addr, &(*ta)->pthread_threads_max, sizeof (int))
00109          != PS_OK)
00110        goto free_return;
00111     }
00112 
00113   /* Similar for the maximum number of thread local data keys.  */
00114   if (td_lookup (ps, LINUXTHREADS_PTHREAD_KEYS_MAX, &addr) != PS_OK)
00115     (*ta)->pthread_keys_max = PTHREAD_KEYS_MAX;
00116   else
00117     {
00118       if (ps_pdread (ps, addr, &(*ta)->pthread_keys_max, sizeof (int))
00119          != PS_OK)
00120        goto free_return;
00121     }
00122 
00123   /* And for the size of the second level arrays for the keys.  */
00124   if (td_lookup (ps, LINUXTHREADS_PTHREAD_SIZEOF_DESCR, &addr) != PS_OK)
00125     (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct);
00126   else
00127     {
00128       if (ps_pdread (ps, addr, &(*ta)->sizeof_descr, sizeof (int)) != PS_OK)
00129        goto free_return;
00130       /* Don't let bogons in the inferior make us mess ourselves.  */
00131       if ((*ta)->sizeof_descr > sizeof (struct _pthread_descr_struct))
00132        (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct);
00133     }
00134 
00135   /* Now add the new agent descriptor to the list.  */
00136   elemp = (struct agent_list *) malloc (sizeof (struct agent_list));
00137   if (elemp == NULL)
00138     {
00139       /* Argh, now that everything else worked...  */
00140       free (*ta);
00141       return TD_MALLOC;
00142     }
00143 
00144   /* We don't care for thread-safety here.  */
00145   elemp->ta = *ta;
00146   elemp->next = __td_agent_list;
00147   __td_agent_list = elemp;
00148 
00149   return TD_OK;
00150 }