Back to index

glibc  2.9
td_ta_map_lwp2thr.c
Go to the documentation of this file.
00001 /* Which thread is running on an LWP?
00002    Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include "thread_dbP.h"
00021 #include <stdlib.h>
00022 #include <byteswap.h>
00023 #include <sys/procfs.h>
00024 
00025 
00026 td_err_e
00027 __td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
00028                        lwpid_t lwpid, td_thrhandle_t *th)
00029 {
00030   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
00031   ps_err_e err;
00032   td_err_e terr;
00033   prgregset_t regs;
00034   psaddr_t addr;
00035 
00036   LOG ("td_ta_map_lwp2thr");
00037 
00038   /* Test whether the TA parameter is ok.  */
00039   if (! ta_ok (ta))
00040     return TD_BADTA;
00041 
00042   if (ta->ta_howto == ta_howto_unknown)
00043     {
00044       /* We need to read in from the inferior the instructions what to do.  */
00045       psaddr_t howto;
00046 
00047       err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
00048       if (err == PS_OK)
00049        {
00050          err = ps_pdread (ta->ph, howto,
00051                         &ta->ta_howto_data.const_thread_area,
00052                         sizeof ta->ta_howto_data.const_thread_area);
00053          if (err != PS_OK)
00054            return TD_ERR;
00055          ta->ta_howto = ta_howto_const_thread_area;
00056          if (ta->ta_howto_data.const_thread_area & 0xff000000U)
00057            ta->ta_howto_data.const_thread_area
00058              = bswap_32 (ta->ta_howto_data.const_thread_area);
00059        }
00060       else
00061        {
00062          switch (sizeof (regs[0]))
00063            {
00064            case 8:
00065              err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
00066              if (err == PS_OK)
00067               ta->ta_howto = ta_howto_reg;
00068              else if (err == PS_NOSYM)
00069               {
00070                 err = td_lookup (ta->ph,
00071                                SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
00072                                &howto);
00073                 if (err == PS_OK)
00074                   ta->ta_howto = ta_howto_reg_thread_area;
00075               }
00076              break;
00077 
00078            case 4:
00079              err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
00080              if (err == PS_OK)
00081               ta->ta_howto = ta_howto_reg;
00082              else if (err == PS_NOSYM)
00083               {
00084                 err = td_lookup (ta->ph,
00085                                SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
00086                                &howto);
00087                 if (err == PS_OK)
00088                   ta->ta_howto = ta_howto_reg_thread_area;
00089               }
00090              break;
00091 
00092            default:
00093              abort ();
00094              return TD_DBERR;
00095            }
00096 
00097          if (err != PS_OK)
00098            return TD_DBERR;
00099 
00100          /* For either of these methods we read in the same descriptor.  */
00101          err = ps_pdread (ta->ph, howto,
00102                         ta->ta_howto_data.reg, DB_SIZEOF_DESC);
00103          if (err != PS_OK)
00104            return TD_ERR;
00105          if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
00106            return TD_DBERR;
00107          if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
00108            {
00109              /* Byte-swap these words, though we leave the size word
00110                in native order as the handy way to distinguish.  */
00111              DB_DESC_OFFSET (ta->ta_howto_data.reg)
00112               = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
00113              DB_DESC_NELEM (ta->ta_howto_data.reg)
00114               = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
00115            }
00116        }
00117     }
00118 
00119   switch (ta->ta_howto)
00120     {
00121     default:
00122       return TD_DBERR;
00123 
00124     case ta_howto_reg:
00125       /* On most machines, we are just looking at a register.  */
00126       if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
00127        return TD_ERR;
00128       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
00129                                 0, regs, &addr);
00130       if (terr != TD_OK)
00131        return terr;
00132 
00133       /* In this descriptor the nelem word is overloaded as the bias.  */
00134       addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
00135       th->th_unique = addr;
00136       break;
00137 
00138     case ta_howto_const_thread_area:
00139       /* Some hosts don't have this call and this case won't be used.  */
00140 # pragma weak ps_get_thread_area
00141       if (&ps_get_thread_area == NULL)
00142        return TD_NOCAPAB;
00143 
00144       /* A la x86-64, there is a magic index for get_thread_area.  */
00145       if (ps_get_thread_area (ta->ph, lwpid,
00146                            ta->ta_howto_data.const_thread_area,
00147                            &th->th_unique) != PS_OK)
00148        return TD_ERR;       /* XXX Other error value?  */
00149       break;
00150 
00151     case ta_howto_reg_thread_area:
00152       if (&ps_get_thread_area == NULL)
00153        return TD_NOCAPAB;
00154 
00155       /* A la i386, a register holds the index for get_thread_area.  */
00156       if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
00157        return TD_ERR;
00158       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area,
00159                                 -1, 0, regs, &addr);
00160       if (terr != TD_OK)
00161        return terr;
00162       /* In this descriptor the nelem word is overloaded as scale factor.  */
00163       if (ps_get_thread_area
00164          (ta->ph, lwpid,
00165           ((addr - (psaddr_t) 0)
00166            >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
00167           &th->th_unique) != PS_OK)
00168        return TD_ERR;       /* XXX Other error value?  */
00169       break;
00170     }
00171 
00172   /* Found it.  Now complete the `td_thrhandle_t' object.  */
00173   th->th_ta_p = ta;
00174 
00175   return TD_OK;
00176 }
00177 
00178 td_err_e
00179 td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
00180                  lwpid_t lwpid, td_thrhandle_t *th)
00181 {
00182   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
00183 
00184   /* We cannot rely on thread registers and such information at all
00185      before __pthread_initialize_minimal has gotten far enough.  They
00186      sometimes contain garbage that would confuse us, left by the kernel
00187      at exec.  So if it looks like initialization is incomplete, we only
00188      fake a special descriptor for the initial thread.  */
00189 
00190   psaddr_t list;
00191   td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
00192   if (err != TD_OK)
00193     return err;
00194 
00195   err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
00196   if (err != TD_OK)
00197     return err;
00198 
00199   if (list == 0)
00200     {
00201       if (ps_getpid (ta->ph) != lwpid)
00202        return TD_ERR;
00203       th->th_ta_p = ta;
00204       th->th_unique = 0;
00205       return TD_OK;
00206     }
00207 
00208   return __td_ta_lookup_th_unique (ta_arg, lwpid, th);
00209 }