Back to index

glibc  2.9
Functions
td_ta_map_lwp2thr.c File Reference
#include "thread_dbP.h"
#include <stdlib.h>
#include <byteswap.h>
#include <sys/procfs.h>

Go to the source code of this file.

Functions

td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta_arg, lwpid_t lwpid, td_thrhandle_t *th)
td_err_e td_ta_map_lwp2thr (const td_thragent_t *ta_arg, lwpid_t lwpid, td_thrhandle_t *th)

Function Documentation

td_err_e __td_ta_lookup_th_unique ( const td_thragent_t *  ta_arg,
lwpid_t  lwpid,
td_thrhandle_t th 
)

Definition at line 27 of file td_ta_map_lwp2thr.c.

{
  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
  ps_err_e err;
  td_err_e terr;
  prgregset_t regs;
  psaddr_t addr;

  LOG ("td_ta_map_lwp2thr");

  /* Test whether the TA parameter is ok.  */
  if (! ta_ok (ta))
    return TD_BADTA;

  if (ta->ta_howto == ta_howto_unknown)
    {
      /* We need to read in from the inferior the instructions what to do.  */
      psaddr_t howto;

      err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
      if (err == PS_OK)
       {
         err = ps_pdread (ta->ph, howto,
                        &ta->ta_howto_data.const_thread_area,
                        sizeof ta->ta_howto_data.const_thread_area);
         if (err != PS_OK)
           return TD_ERR;
         ta->ta_howto = ta_howto_const_thread_area;
         if (ta->ta_howto_data.const_thread_area & 0xff000000U)
           ta->ta_howto_data.const_thread_area
             = bswap_32 (ta->ta_howto_data.const_thread_area);
       }
      else
       {
         switch (sizeof (regs[0]))
           {
           case 8:
             err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
             if (err == PS_OK)
              ta->ta_howto = ta_howto_reg;
             else if (err == PS_NOSYM)
              {
                err = td_lookup (ta->ph,
                               SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
                               &howto);
                if (err == PS_OK)
                  ta->ta_howto = ta_howto_reg_thread_area;
              }
             break;

           case 4:
             err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
             if (err == PS_OK)
              ta->ta_howto = ta_howto_reg;
             else if (err == PS_NOSYM)
              {
                err = td_lookup (ta->ph,
                               SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
                               &howto);
                if (err == PS_OK)
                  ta->ta_howto = ta_howto_reg_thread_area;
              }
             break;

           default:
             abort ();
             return TD_DBERR;
           }

         if (err != PS_OK)
           return TD_DBERR;

         /* For either of these methods we read in the same descriptor.  */
         err = ps_pdread (ta->ph, howto,
                        ta->ta_howto_data.reg, DB_SIZEOF_DESC);
         if (err != PS_OK)
           return TD_ERR;
         if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
           return TD_DBERR;
         if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
           {
             /* Byte-swap these words, though we leave the size word
               in native order as the handy way to distinguish.  */
             DB_DESC_OFFSET (ta->ta_howto_data.reg)
              = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
             DB_DESC_NELEM (ta->ta_howto_data.reg)
              = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
           }
       }
    }

  switch (ta->ta_howto)
    {
    default:
      return TD_DBERR;

    case ta_howto_reg:
      /* On most machines, we are just looking at a register.  */
      if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
       return TD_ERR;
      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
                                0, regs, &addr);
      if (terr != TD_OK)
       return terr;

      /* In this descriptor the nelem word is overloaded as the bias.  */
      addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
      th->th_unique = addr;
      break;

    case ta_howto_const_thread_area:
      /* Some hosts don't have this call and this case won't be used.  */
# pragma weak ps_get_thread_area
      if (&ps_get_thread_area == NULL)
       return TD_NOCAPAB;

      /* A la x86-64, there is a magic index for get_thread_area.  */
      if (ps_get_thread_area (ta->ph, lwpid,
                           ta->ta_howto_data.const_thread_area,
                           &th->th_unique) != PS_OK)
       return TD_ERR;       /* XXX Other error value?  */
      break;

    case ta_howto_reg_thread_area:
      if (&ps_get_thread_area == NULL)
       return TD_NOCAPAB;

      /* A la i386, a register holds the index for get_thread_area.  */
      if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
       return TD_ERR;
      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area,
                                -1, 0, regs, &addr);
      if (terr != TD_OK)
       return terr;
      /* In this descriptor the nelem word is overloaded as scale factor.  */
      if (ps_get_thread_area
         (ta->ph, lwpid,
          ((addr - (psaddr_t) 0)
           >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
          &th->th_unique) != PS_OK)
       return TD_ERR;       /* XXX Other error value?  */
      break;
    }

  /* Found it.  Now complete the `td_thrhandle_t' object.  */
  th->th_ta_p = ta;

  return TD_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

td_err_e td_ta_map_lwp2thr ( const td_thragent_t *  ta_arg,
lwpid_t  lwpid,
td_thrhandle_t th 
)

Definition at line 179 of file td_ta_map_lwp2thr.c.

{
  td_thragent_t *const ta = (td_thragent_t *) ta_arg;

  /* We cannot rely on thread registers and such information at all
     before __pthread_initialize_minimal has gotten far enough.  They
     sometimes contain garbage that would confuse us, left by the kernel
     at exec.  So if it looks like initialization is incomplete, we only
     fake a special descriptor for the initial thread.  */

  psaddr_t list;
  td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
  if (err != TD_OK)
    return err;

  err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
  if (err != TD_OK)
    return err;

  if (list == 0)
    {
      if (ps_getpid (ta->ph) != lwpid)
       return TD_ERR;
      th->th_ta_p = ta;
      th->th_unique = 0;
      return TD_OK;
    }

  return __td_ta_lookup_th_unique (ta_arg, lwpid, th);
}

Here is the call graph for this function: