td_err_e td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback, void *cbdata_p) { td_thragent_t *const ta = (td_thragent_t *) ta_arg; td_err_e err; void *keys; size_t keys_nb, keys_elemsize; psaddr_t addr; uint32_t idx; LOG ("td_ta_tsd_iter"); /* Test whether the TA parameter is ok. */ if (! ta_ok (ta)) return TD_BADTA; /* This makes sure we have the size information on hand. */ addr = 0; err = _td_locate_field (ta, ta->ta_var___pthread_keys, SYM_DESC___pthread_keys, (psaddr_t) 0 + 1, &addr); if (err != TD_OK) return err; /* Now copy in the entire array of key descriptors. */ keys_elemsize = (addr - (psaddr_t) 0) / 8; keys_nb = keys_elemsize * DB_DESC_NELEM (ta->ta_var___pthread_keys); keys = __alloca (keys_nb); err = DB_GET_SYMBOL (addr, ta, __pthread_keys); if (err != TD_OK) return err; if (ps_pdread (ta->ph, addr, keys, keys_nb) != PS_OK) return TD_ERR; /* Now get all descriptors, one after the other. */ for (idx = 0; idx < DB_DESC_NELEM (ta->ta_var___pthread_keys); ++idx) { psaddr_t seq, destr; err = DB_GET_FIELD_LOCAL (seq, ta, keys, pthread_key_struct, seq, 0); if (err != TD_OK) return err; if (((uintptr_t) seq) & 1) { err = DB_GET_FIELD_LOCAL (destr, ta, keys, pthread_key_struct, destr, 0); if (err != TD_OK) return err; /* Return with an error if the callback returns a nonzero value. */ if (callback ((thread_key_t) idx, destr, cbdata_p) != 0) return TD_DBERR; } /* Advance to the next element in the copied array. */ keys += keys_elemsize; } return TD_OK; }
td_err_e _td_locate_field (td_thragent_t *ta, db_desc_t desc, int descriptor_name, psaddr_t idx, psaddr_t *address) { uint32_t elemsize; if (DB_DESC_SIZE (desc) == 0) { /* Read the information about this field from the inferior. */ psaddr_t descptr; ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr); if (err == PS_NOSYM) return TD_NOCAPAB; if (err == PS_OK) err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC); if (err != PS_OK) return TD_ERR; if (DB_DESC_SIZE (desc) == 0) return TD_DBERR; if (DB_DESC_SIZE (desc) & 0xff000000U) { /* Byte-swap these words, though we leave the size word in native order as the handy way to distinguish. */ DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc)); DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc)); } } if (idx != 0 && DB_DESC_NELEM (desc) != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc)) /* This is an internal indicator to callers with nonzero IDX that the IDX value is too big. */ return TD_NOAPLIC; elemsize = DB_DESC_SIZE (desc); if (elemsize & 0xff000000U) elemsize = bswap_32 (elemsize); *address += (int32_t) DB_DESC_OFFSET (desc); *address += (elemsize / 8 * (idx - (psaddr_t) 0)); return TD_OK; }
td_err_e td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) { td_err_e err; psaddr_t tk_seq, level1, level2, seq, value; void *copy; uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd; LOG ("td_thr_tsd"); /* Get the key entry. */ err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk); if (err == TD_NOAPLIC) return TD_BADKEY; if (err != TD_OK) return err; /* Fail if this key is not at all used. */ if (((uintptr_t) tk_seq & 1) == 0) return TD_BADKEY; /* This makes sure we have the size information on hand. */ err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2, data, 1); if (err != TD_OK) return err; /* Compute the indeces. */ pthread_key_2ndlevel_size = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data); idx1st = tk / pthread_key_2ndlevel_size; idx2nd = tk % pthread_key_2ndlevel_size; /* Now fetch the first level pointer. */ err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread, specific, idx1st); if (err == TD_NOAPLIC) return TD_DBERR; if (err != TD_OK) return err; /* Check the pointer to the second level array. */ if (level1 == 0) return TD_NOTSD; /* Locate the element within the second level array. */ err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, level1, pthread_key_data_level2, data, idx2nd); if (err == TD_NOAPLIC) return TD_DBERR; if (err != TD_OK) return err; /* Now copy in that whole structure. */ err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data); if (err != TD_OK) return err; /* Check whether the data is valid. */ err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0); if (err != TD_OK) return err; if (seq != tk_seq) return TD_NOTSD; /* Finally, fetch the value. */ err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data, data, 0); if (err == TD_OK) *data = value; return err; }