(linenum→info "unix/slp.c:2238")

glibc/2.7/nptl_db/td_ta_map_lwp2thr.c

    1: /* Which thread is running on an LWP?
    2:    Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include "thread_dbP.h"
   21: #include <stdlib.h>
   22: #include <byteswap.h>
   23: #include <sys/procfs.h>
   24: 
   25: 
   26: td_err_e
   27: __td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
   28:                           lwpid_t lwpid, td_thrhandle_t *th)
   29: {
   30:   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
   31:   ps_err_e err;
   32:   td_err_e terr;
   33:   prgregset_t regs;
   34:   psaddr_t addr;
   35: 
   36:   LOG ("td_ta_map_lwp2thr");
   37: 
   38:   /* Test whether the TA parameter is ok.  */
   39:   if (! ta_ok (ta))
   40:     return TD_BADTA;
   41: 
   42:   if (ta->ta_howto == ta_howto_unknown)
   43:     {
   44:       /* We need to read in from the inferior the instructions what to do.  */
   45:       psaddr_t howto;
   46: 
   47:       err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
   48:       if (err == PS_OK)
   49:         {
   50:           err = ps_pdread (ta->ph, howto,
   51:                            &ta->ta_howto_data.const_thread_area,
   52:                            sizeof ta->ta_howto_data.const_thread_area);
   53:           if (err != PS_OK)
   54:             return TD_ERR;
   55:           ta->ta_howto = ta_howto_const_thread_area;
   56:           if (ta->ta_howto_data.const_thread_area & 0xff000000U)
   57:             ta->ta_howto_data.const_thread_area
   58:               = bswap_32 (ta->ta_howto_data.const_thread_area);
   59:         }
   60:       else
   61:         {
   62:           switch (sizeof (regs[0]))
   63:             {
   64:             case 8:
   65:               err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
   66:               if (err == PS_OK)
   67:                 ta->ta_howto = ta_howto_reg;
   68:               else if (err == PS_NOSYM)
   69:                 {
   70:                   err = td_lookup (ta->ph,
   71:                                    SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
   72:                                    &howto);
   73:                   if (err == PS_OK)
   74:                     ta->ta_howto = ta_howto_reg_thread_area;
   75:                 }
   76:               break;
   77: 
   78:             case 4:
   79:               err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
   80:               if (err == PS_OK)
   81:                 ta->ta_howto = ta_howto_reg;
   82:               else if (err == PS_NOSYM)
   83:                 {
   84:                   err = td_lookup (ta->ph,
   85:                                    SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
   86:                                    &howto);
   87:                   if (err == PS_OK)
   88:                     ta->ta_howto = ta_howto_reg_thread_area;
   89:                 }
   90:               break;
   91: 
   92:             default:
   93:               abort ();
   94:               return TD_DBERR;
   95:             }
   96: 
   97:           if (err != PS_OK)
   98:             return TD_DBERR;
   99: 
  100:           /* For either of these methods we read in the same descriptor.  */
  101:           err = ps_pdread (ta->ph, howto,
  102:                            ta->ta_howto_data.reg, DB_SIZEOF_DESC);
  103:           if (err != PS_OK)
  104:             return TD_ERR;
  105:           if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
  106:             return TD_DBERR;
  107:           if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
  108:             {
  109:               /* Byte-swap these words, though we leave the size word
  110:                  in native order as the handy way to distinguish.  */
  111:               DB_DESC_OFFSET (ta->ta_howto_data.reg)
  112:                 = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
  113:               DB_DESC_NELEM (ta->ta_howto_data.reg)
  114:                 = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
  115:             }
  116:         }
  117:     }
  118: 
  119:   switch (ta->ta_howto)
  120:     {
  121:     default:
  122:       return TD_DBERR;
  123: 
  124:     case ta_howto_reg:
  125:       /* On most machines, we are just looking at a register.  */
  126:       if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
  127:         return TD_ERR;
  128:       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
  129:                                     0, regs, &addr);
  130:       if (terr != TD_OK)
  131:         return terr;
  132: 
  133:       /* In this descriptor the nelem word is overloaded as the bias.  */
  134:       addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
  135:       th->th_unique = addr;
  136:       break;
  137: 
  138:     case ta_howto_const_thread_area:
  139:       /* Some hosts don't have this call and this case won't be used.  */
  140: # pragma weak ps_get_thread_area
  141:       if (&ps_get_thread_area == NULL)
  142:         return TD_NOCAPAB;
  143: 
  144:       /* A la x86-64, there is a magic index for get_thread_area.  */
  145:       if (ps_get_thread_area (ta->ph, lwpid,
  146:                               ta->ta_howto_data.const_thread_area,
  147:                               &th->th_unique) != PS_OK)
  148:         return TD_ERR; /* XXX Other error value?  */
  149:       break;
  150: 
  151:     case ta_howto_reg_thread_area:
  152:       if (&ps_get_thread_area == NULL)
  153:         return TD_NOCAPAB;
  154: 
  155:       /* A la i386, a register holds the index for get_thread_area.  */
  156:       if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
  157:         return TD_ERR;
  158:       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area,
  159:                                     -1, 0, regs, &addr);
  160:       if (terr != TD_OK)
  161:         return terr;
  162:       /* In this descriptor the nelem word is overloaded as scale factor.  */
  163:       if (ps_get_thread_area
  164:           (ta->ph, lwpid,
  165:            ((addr - (psaddr_t) 0)
  166:             >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
  167:            &th->th_unique) != PS_OK)
  168:         return TD_ERR; /* XXX Other error value?  */
  169:       break;
  170:     }
  171: 
  172:   /* Found it.  Now complete the `td_thrhandle_t' object.  */
  173:   th->th_ta_p = ta;
  174: 
  175:   return TD_OK;
  176: }
  177: 
  178: td_err_e
  179: td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
  180:                    lwpid_t lwpid, td_thrhandle_t *th)
  181: {
  182:   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
  183: 
  184:   /* We cannot rely on thread registers and such information at all
  185:      before __pthread_initialize_minimal has gotten far enough.  They
  186:      sometimes contain garbage that would confuse us, left by the kernel
  187:      at exec.  So if it looks like initialization is incomplete, we only
  188:      fake a special descriptor for the initial thread.  */
  189: 
  190:   psaddr_t list;
  191:   td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
  192:   if (err != TD_OK)
  193:     return err;
  194: 
  195:   err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
  196:   if (err != TD_OK)
  197:     return err;
  198: 
  199:   if (list == 0)
  200:     {
  201:       if (ps_getpid (ta->ph) != lwpid)
  202:         return TD_ERR;
  203:       th->th_ta_p = ta;
  204:       th->th_unique = 0;
  205:       return TD_OK;
  206:     }
  207: 
  208:   return __td_ta_lookup_th_unique (ta_arg, lwpid, th);
  209: }
Syntax (Markdown)